diff --git a/vendor/code.ivysaur.me/imagequant/.gitignore b/vendor/code.ivysaur.me/imagequant/.gitignore
deleted file mode 100644
index 61549eb..0000000
--- a/vendor/code.ivysaur.me/imagequant/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-cmd/gopngquant/gopngquant
-cmd/gopngquant/gopngquant.exe
diff --git a/vendor/code.ivysaur.me/imagequant/Attributes.go b/vendor/code.ivysaur.me/imagequant/Attributes.go
deleted file mode 100644
index f2ca262..0000000
--- a/vendor/code.ivysaur.me/imagequant/Attributes.go
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
-Copyright (c) 2016, The go-imagequant author(s)
-
-Permission to use, copy, modify, and/or distribute this software for any purpose
-with or without fee is hereby granted, provided that the above copyright notice
-and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD TO
-THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
-IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
-OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
-ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-*/
-
-package imagequant
-
-import (
- "errors"
-)
-
-/*
-#include "libimagequant.h"
-*/
-import "C"
-
-type Attributes struct {
- p *C.struct_liq_attr
-}
-
-// Callers MUST call Release() on the returned object to free memory.
-func NewAttributes() (*Attributes, error) {
- pAttr := C.liq_attr_create()
- if pAttr == nil { // nullptr
- return nil, errors.New("Unsupported platform")
- }
-
- return &Attributes{p: pAttr}, nil
-}
-
-const (
- COLORS_MIN = 2
- COLORS_MAX = 256
-)
-
-func (this *Attributes) SetMaxColors(colors int) error {
- return translateError(C.liq_set_max_colors(this.p, C.int(colors)))
-}
-
-func (this *Attributes) GetMaxColors() int {
- return int(C.liq_get_max_colors(this.p))
-}
-
-const (
- QUALITY_MIN = 0
- QUALITY_MAX = 100
-)
-
-func (this *Attributes) SetQuality(minimum, maximum int) error {
- return translateError(C.liq_set_quality(this.p, C.int(minimum), C.int(maximum)))
-}
-
-func (this *Attributes) GetMinQuality() int {
- return int(C.liq_get_min_quality(this.p))
-}
-
-func (this *Attributes) GetMaxQuality() int {
- return int(C.liq_get_max_quality(this.p))
-}
-
-const (
- SPEED_SLOWEST = 1
- SPEED_DEFAULT = 3
- SPEED_FASTEST = 10
-)
-
-func (this *Attributes) SetSpeed(speed int) error {
- return translateError(C.liq_set_speed(this.p, C.int(speed)))
-}
-
-func (this *Attributes) GetSpeed() int {
- return int(C.liq_get_speed(this.p))
-}
-
-func (this *Attributes) SetMinOpacity(min int) error {
- return translateError(C.liq_set_min_opacity(this.p, C.int(min)))
-}
-
-func (this *Attributes) GetMinOpacity() int {
- return int(C.liq_get_min_opacity(this.p))
-}
-
-func (this *Attributes) SetMinPosterization(bits int) error {
- return translateError(C.liq_set_min_posterization(this.p, C.int(bits)))
-}
-
-func (this *Attributes) GetMinPosterization() int {
- return int(C.liq_get_min_posterization(this.p))
-}
-
-func (this *Attributes) SetLastIndexTransparent(is_last int) {
- C.liq_set_last_index_transparent(this.p, C.int(is_last))
-}
-
-func (this *Attributes) CreateHistogram() *Histogram {
- ptr := C.liq_histogram_create(this.p)
- return &Histogram{p: ptr}
-}
-
-// Free memory. Callers must not use this object after Release has been called.
-func (this *Attributes) Release() {
- C.liq_attr_destroy(this.p)
-}
diff --git a/vendor/code.ivysaur.me/imagequant/COPYRIGHT b/vendor/code.ivysaur.me/imagequant/COPYRIGHT
deleted file mode 100644
index 3514d66..0000000
--- a/vendor/code.ivysaur.me/imagequant/COPYRIGHT
+++ /dev/null
@@ -1,641 +0,0 @@
-
-libimagequant is derived from code by Jef Poskanzer and Greg Roelofs
-licensed under pngquant's original license (at the end of this file),
-and contains extensive changes and additions by Kornel Lesiński
-licensed under GPL v3.
-
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-libimagequant © 2009-2016 by Kornel Lesiński.
-
- GNU GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc.
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
-
- The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works. By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users. We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors. 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
-them 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 prevent others from denying you
-these rights or asking you to surrender the rights. Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received. 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.
-
- Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
- For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software. For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
- Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so. This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software. The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable. Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products. If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
- Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary. To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- TERMS AND CONDITIONS
-
- 0. Definitions.
-
- "This License" refers to version 3 of the GNU General Public License.
-
- "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
- "The Program" refers to any copyrightable work licensed under this
-License. Each licensee is addressed as "you". "Licensees" and
-"recipients" may be individuals or organizations.
-
- To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy. The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
- A "covered work" means either the unmodified Program or a work based
-on the Program.
-
- To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy. Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
- To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies. Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
- An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License. If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
- 1. Source Code.
-
- The "source code" for a work means the preferred form of the work
-for making modifications to it. "Object code" means any non-source
-form of a work.
-
- A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
- The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form. A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
- The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities. However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work. For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
- The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
- The Corresponding Source for a work in source code form is that
-same work.
-
- 2. Basic Permissions.
-
- All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met. This License explicitly affirms your unlimited
-permission to run the unmodified Program. The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work. This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
- You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force. You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright. Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
- Conveying under any other circumstances is permitted solely under
-the conditions stated below. Sublicensing is not allowed; section 10
-makes it unnecessary.
-
- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
- No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
- When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
- 4. Conveying Verbatim Copies.
-
- You may convey 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;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
- You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
- 5. Conveying Modified Source Versions.
-
- You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
- a) The work must carry prominent notices stating that you modified
- it, and giving a relevant date.
-
- b) The work must carry prominent notices stating that it is
- released under this License and any conditions added under section
- 7. This requirement modifies the requirement in section 4 to
- "keep intact all notices".
-
- c) You must license the entire work, as a whole, under this
- License to anyone who comes into possession of a copy. This
- License will therefore apply, along with any applicable section 7
- additional terms, to the whole of the work, and all its parts,
- regardless of how they are packaged. This License gives no
- permission to license the work in any other way, but it does not
- invalidate such permission if you have separately received it.
-
- d) If the work has interactive user interfaces, each must display
- Appropriate Legal Notices; however, if the Program has interactive
- interfaces that do not display Appropriate Legal Notices, your
- work need not make them do so.
-
- A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit. Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
- 6. Conveying Non-Source Forms.
-
- You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
- a) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by the
- Corresponding Source fixed on a durable physical medium
- customarily used for software interchange.
-
- b) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by a
- written offer, valid for at least three years and valid for as
- long as you offer spare parts or customer support for that product
- model, to give anyone who possesses the object code either (1) a
- copy of the Corresponding Source for all the software in the
- product that is covered by this License, on a durable physical
- medium customarily used for software interchange, for a price no
- more than your reasonable cost of physically performing this
- conveying of source, or (2) access to copy the
- Corresponding Source from a network server at no charge.
-
- c) Convey individual copies of the object code with a copy of the
- written offer to provide the Corresponding Source. This
- alternative is allowed only occasionally and noncommercially, and
- only if you received the object code with such an offer, in accord
- with subsection 6b.
-
- d) Convey the object code by offering access from a designated
- place (gratis or for a charge), and offer equivalent access to the
- Corresponding Source in the same way through the same place at no
- further charge. You need not require recipients to copy the
- Corresponding Source along with the object code. If the place to
- copy the object code is a network server, the Corresponding Source
- may be on a different server (operated by you or a third party)
- that supports equivalent copying facilities, provided you maintain
- clear directions next to the object code saying where to find the
- Corresponding Source. Regardless of what server hosts the
- Corresponding Source, you remain obligated to ensure that it is
- available for as long as needed to satisfy these requirements.
-
- e) Convey the object code using peer-to-peer transmission, provided
- you inform other peers where the object code and Corresponding
- Source of the work are being offered to the general public at no
- charge under subsection 6d.
-
- A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
- A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling. In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage. For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product. A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
- "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source. The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
- If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information. But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
- The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed. Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
- Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
- 7. Additional Terms.
-
- "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law. If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
- When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it. (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.) You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
- Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
- a) Disclaiming warranty or limiting liability differently from the
- terms of sections 15 and 16 of this License; or
-
- b) Requiring preservation of specified reasonable legal notices or
- author attributions in that material or in the Appropriate Legal
- Notices displayed by works containing it; or
-
- c) Prohibiting misrepresentation of the origin of that material, or
- requiring that modified versions of such material be marked in
- reasonable ways as different from the original version; or
-
- d) Limiting the use for publicity purposes of names of licensors or
- authors of the material; or
-
- e) Declining to grant rights under trademark law for use of some
- trade names, trademarks, or service marks; or
-
- f) Requiring indemnification of licensors and authors of that
- material by anyone who conveys the material (or modified versions of
- it) with contractual assumptions of liability to the recipient, for
- any liability that these contractual assumptions directly impose on
- those licensors and authors.
-
- All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10. If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term. If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
- If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
- Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
- 8. Termination.
-
- You may not propagate or modify a covered work except as expressly
-provided under this License. Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
- However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
- Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
- Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License. If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
- 9. Acceptance Not Required for Having Copies.
-
- You are not required to accept this License in order to receive or
-run a copy of the Program. Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance. However,
-nothing other than this License grants you permission to propagate or
-modify any covered work. These actions infringe copyright if you do
-not accept this License. Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
- 10. Automatic Licensing of Downstream Recipients.
-
- Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License. You are not responsible
-for enforcing compliance by third parties with this License.
-
- An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations. If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
- You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License. For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
- 11. Patents.
-
- A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based. The
-work thus licensed is called the contributor's "contributor version".
-
- A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version. For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
- Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
- In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement). To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
- If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients. "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
- If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
- A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License. You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
- Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
- 12. No Surrender of Others' Freedom.
-
- If 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 convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all. For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
- 13. Use with the GNU Affero General Public License.
-
- Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work. The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
- 14. Revised Versions of this License.
-
- The Free Software Foundation may publish revised and/or new versions of
-the GNU 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 that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation. If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
- If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
- Later license versions may give you additional or different
-permissions. However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
- 15. Disclaimer of Warranty.
-
- 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.
-
- 16. Limitation of Liability.
-
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-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.
-
- 17. Interpretation of Sections 15 and 16.
-
- If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-© 1989, 1991 by Jef Poskanzer.
-© 1997, 2000, 2002 by Greg Roelofs.
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted, provided
-that the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation. This software is provided "as is" without express or
-implied warranty.
diff --git a/vendor/code.ivysaur.me/imagequant/Histogram.go b/vendor/code.ivysaur.me/imagequant/Histogram.go
deleted file mode 100644
index 183cbce..0000000
--- a/vendor/code.ivysaur.me/imagequant/Histogram.go
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
-Copyright (c) 2016, The go-imagequant author(s)
-
-Permission to use, copy, modify, and/or distribute this software for any purpose
-with or without fee is hereby granted, provided that the above copyright notice
-and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD TO
-THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
-IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
-OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
-ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-*/
-
-package imagequant
-
-/*
-#include "libimagequant.h"
-*/
-import "C"
-
-type Histogram struct {
- p *C.struct_liq_histogram
-}
-
-func (this *Histogram) AddImage(attr *Attributes, img *Image) error {
- return translateError(C.liq_histogram_add_image(this.p, attr.p, img.p))
-}
-
-func (this *Histogram) Quantize(attr *Attributes) (*Result, error) {
- res := Result{}
- liqerr := C.liq_histogram_quantize(this.p, attr.p, &res.p)
- if liqerr != C.LIQ_OK {
- return nil, translateError(liqerr)
- }
-
- return &res, nil
-}
-
-// Free memory. Callers must not use this object after Release has been called.
-func (this *Histogram) Release() {
- C.liq_histogram_destroy(this.p)
-}
diff --git a/vendor/code.ivysaur.me/imagequant/Image.go b/vendor/code.ivysaur.me/imagequant/Image.go
deleted file mode 100644
index 38a5f3d..0000000
--- a/vendor/code.ivysaur.me/imagequant/Image.go
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
-Copyright (c) 2016, The go-imagequant author(s)
-
-Permission to use, copy, modify, and/or distribute this software for any purpose
-with or without fee is hereby granted, provided that the above copyright notice
-and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD TO
-THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
-IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
-OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
-ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-*/
-
-package imagequant
-
-import (
- "errors"
- "unsafe"
-)
-
-/*
-#include "libimagequant.h"
-*/
-import "C"
-
-type Image struct {
- p *C.struct_liq_image
- w, h int
- released bool
-}
-
-// Callers MUST call Release() on the returned object to free memory.
-func NewImage(attr *Attributes, rgba32data string, width, height int, gamma float64) (*Image, error) {
- pImg := C.liq_image_create_rgba(attr.p, unsafe.Pointer(C.CString(rgba32data)), C.int(width), C.int(height), C.double(gamma))
- if pImg == nil {
- return nil, errors.New("Failed to create image (invalid argument)")
- }
-
- return &Image{
- p: pImg,
- w: width,
- h: height,
- released: false,
- }, nil
-}
-
-// Free memory. Callers must not use this object after Release has been called.
-func (this *Image) Release() {
- C.liq_image_destroy(this.p)
- this.released = true
-}
-
-func (this *Image) Quantize(attr *Attributes) (*Result, error) {
- res := Result{
- im: this,
- }
- liqerr := C.liq_image_quantize(this.p, attr.p, &res.p)
- if liqerr != C.LIQ_OK {
- return nil, translateError(liqerr)
- }
-
- return &res, nil
-}
diff --git a/vendor/code.ivysaur.me/imagequant/README.md b/vendor/code.ivysaur.me/imagequant/README.md
deleted file mode 100644
index 7ebc506..0000000
--- a/vendor/code.ivysaur.me/imagequant/README.md
+++ /dev/null
@@ -1,65 +0,0 @@
-# imagequant
-
-Go bindings for libimagequant
-
-`libimagequant` is a library for lossy recompression of PNG images to reduce their filesize. It is used by the `pngquant` tool. This `go-imagequant` project is a set of bindings for libimagequant to enable its use from the Go programming language.
-
-This binding was written by hand. The result is somewhat more idiomatic than an automated conversion, but some `defer foo.Release()` calls are required for memory management.
-
-Written in Golang
-
-## Usage
-
-Usage example is provided by a sample utility `cmd/gopngquant` which mimics some functionality of the upstream `pngquant`.
-
-The sample utility has the following options:
-
-```
-Usage of gopngquant:
- -In string
- Input filename
- -Out string
- Output filename
- -Speed int
- Speed (1 slowest, 10 fastest) (default 3)
- -Version
-```
-
-## Building
-
-This package can be installed via go get: `go get code.ivysaur.me/imagequant`
-[go-get]code.ivysaur.me/imagequant git https://git.ivysaur.me/code.ivysaur.me/imagequant.git[/go-get]
-
-The expected package path is `code.ivysaur.me/imagequant`. Build via `go build`.
-
-This is a CGO package and requires a C compiler installed. However, if you use `go install` then future invocations of `go build` do not require the C compiler to be present.
-
-The `imagequant.go` file also declares a number of `CFLAGS` for GCC that allow the included libimagequant (2.8 git-a425e83) to build in an optimal way without using the upstream configure/make scripts.
-
-## License
-
-I am releasing this binding under the ISC license, however, `libimagequant` itself is released under GPLv3-or-later and/or commercial licenses. You must comply with the terms of such a license when using this binding in a Go project.
-
-## Changelog
-
-2018-12-31 v2.12.2-go1.2
-- go-imagequant: Update bundled libimagequant from 2.9.0 to 2.12.2
-- build: Switch to Go Modules
-- build: Update bundled CFLAGS for new CGo whitelist (reduces performance)
-- build: Remove nonportable Cygwin makefile
-
-2017-03-03 v2.9.0-go1.1
-- *Previously tagged as 2.9go1.1*
-- go-imagequant: Update bundled libimagequant from 2.8.0 to 2.9.0
-- go-imagequant: Separate `CGO_LDFLAGS` for Linux and Windows targets
-- gopngquant: Fix an issue with non-square images
-
-2016-11-24 v2.8.0-go1.0
-- *Previously tagged as 2.8go1.0*
-- Initial public release
-
-## See also
-
-- Pngquant homepage https://pngquant.org/
-- Pngquant source code https://github.com/pornel/pngquant
-- Libimagequant source code https://github.com/ImageOptim/libimagequant
diff --git a/vendor/code.ivysaur.me/imagequant/Result.go b/vendor/code.ivysaur.me/imagequant/Result.go
deleted file mode 100644
index d084c95..0000000
--- a/vendor/code.ivysaur.me/imagequant/Result.go
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
-Copyright (c) 2016, The go-imagequant author(s)
-
-Permission to use, copy, modify, and/or distribute this software for any purpose
-with or without fee is hereby granted, provided that the above copyright notice
-and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD TO
-THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
-IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
-OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
-ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-*/
-
-package imagequant
-
-import (
- "image/color"
- "unsafe"
-)
-
-/*
-#include "libimagequant.h"
-*/
-import "C"
-
-// Callers must not use this object once Release has been called on the parent
-// Image struct.
-type Result struct {
- p *C.struct_liq_result
- im *Image
-}
-
-func (this *Result) SetDitheringLevel(dither_level float32) error {
- return translateError(C.liq_set_dithering_level(this.p, C.float(dither_level)))
-}
-
-func (this *Result) GetQuantizationError() float64 {
- return float64(C.liq_get_quantization_error(this.p))
-}
-
-func (this *Result) GetRemappingError() float64 {
- return float64(C.liq_get_remapping_error(this.p))
-}
-
-func (this *Result) GetQuantizationQuality() float64 {
- return float64(C.liq_get_quantization_quality(this.p))
-}
-
-func (this *Result) GetRemappingQuality() float64 {
- return float64(C.liq_get_remapping_quality(this.p))
-}
-
-func (this *Result) SetOutputGamma(gamma float64) error {
- return translateError(C.liq_set_output_gamma(this.p, C.double(gamma)))
-}
-
-func (this *Result) GetImageWidth() int {
- // C.liq_image_get_width
- return this.im.w
-}
-
-func (this *Result) GetImageHeight() int {
- // C.liq_image_get_height
- return this.im.h
-}
-
-func (this *Result) GetOutputGamma() float64 {
- return float64(C.liq_get_output_gamma(this.p))
-}
-
-func (this *Result) WriteRemappedImage() ([]byte, error) {
- if this.im.released {
- return nil, ErrUseAfterFree
- }
-
- buff_size := this.im.w * this.im.h
- buff := make([]byte, buff_size)
-
- iqe := C.liq_write_remapped_image(this.p, this.im.p, unsafe.Pointer(&buff[0]), C.size_t(buff_size))
- if iqe != C.LIQ_OK {
- return nil, translateError(iqe)
- }
-
- return buff, nil
-}
-
-func (this *Result) GetPalette() color.Palette {
- ptr := C.liq_get_palette(this.p) // copy struct content
- max := int(ptr.count)
-
- ret := make([]color.Color, max)
- for i := 0; i < max; i += 1 {
- ret[i] = color.RGBA{
- R: uint8(ptr.entries[i].r),
- G: uint8(ptr.entries[i].g),
- B: uint8(ptr.entries[i].b),
- A: uint8(ptr.entries[i].a),
- }
- }
-
- return ret
-}
-
-// Free memory. Callers must not use this object after Release has been called.
-func (this *Result) Release() {
- C.liq_result_destroy(this.p)
-}
diff --git a/vendor/code.ivysaur.me/imagequant/blur.c b/vendor/code.ivysaur.me/imagequant/blur.c
deleted file mode 100644
index 7f0a716..0000000
--- a/vendor/code.ivysaur.me/imagequant/blur.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
-© 2011-2015 by Kornel Lesiński.
-
-This file is part of libimagequant.
-
-libimagequant 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 3 of the License, or
-(at your option) any later version.
-
-libimagequant 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 libimagequant. If not, see .
-*/
-
-#include "libimagequant.h"
-#include "pam.h"
-#include "blur.h"
-
-/*
- Blurs image horizontally (width 2*size+1) and writes it transposed to dst (called twice gives 2d blur)
- */
-static void transposing_1d_blur(unsigned char *restrict src, unsigned char *restrict dst, unsigned int width, unsigned int height, const unsigned int size)
-{
- assert(size > 0);
-
- for(unsigned int j=0; j < height; j++) {
- unsigned char *restrict row = src + j*width;
-
- // accumulate sum for pixels outside line
- unsigned int sum;
- sum = row[0]*size;
- for(unsigned int i=0; i < size; i++) {
- sum += row[i];
- }
-
- // blur with left side outside line
- for(unsigned int i=0; i < size; i++) {
- sum -= row[0];
- sum += row[i+size];
-
- dst[i*height + j] = sum / (size*2);
- }
-
- for(unsigned int i=size; i < width-size; i++) {
- sum -= row[i-size];
- sum += row[i+size];
-
- dst[i*height + j] = sum / (size*2);
- }
-
- // blur with right side outside line
- for(unsigned int i=width-size; i < width; i++) {
- sum -= row[i-size];
- sum += row[width-1];
-
- dst[i*height + j] = sum / (size*2);
- }
- }
-}
-
-/**
- * Picks maximum of neighboring pixels (blur + lighten)
- */
-LIQ_PRIVATE void liq_max3(unsigned char *src, unsigned char *dst, unsigned int width, unsigned int height)
-{
- for(unsigned int j=0; j < height; j++) {
- const unsigned char *row = src + j*width,
- *prevrow = src + (j > 1 ? j-1 : 0)*width,
- *nextrow = src + MIN(height-1,j+1)*width;
-
- unsigned char prev,curr=row[0],next=row[0];
-
- for(unsigned int i=0; i < width-1; i++) {
- prev=curr;
- curr=next;
- next=row[i+1];
-
- unsigned char t1 = MAX(prev,next);
- unsigned char t2 = MAX(nextrow[i],prevrow[i]);
- *dst++ = MAX(curr,MAX(t1,t2));
- }
- unsigned char t1 = MAX(curr,next);
- unsigned char t2 = MAX(nextrow[width-1],prevrow[width-1]);
- *dst++ = MAX(t1,t2);
- }
-}
-
-/**
- * Picks minimum of neighboring pixels (blur + darken)
- */
-LIQ_PRIVATE void liq_min3(unsigned char *src, unsigned char *dst, unsigned int width, unsigned int height)
-{
- for(unsigned int j=0; j < height; j++) {
- const unsigned char *row = src + j*width,
- *prevrow = src + (j > 1 ? j-1 : 0)*width,
- *nextrow = src + MIN(height-1,j+1)*width;
-
- unsigned char prev,curr=row[0],next=row[0];
-
- for(unsigned int i=0; i < width-1; i++) {
- prev=curr;
- curr=next;
- next=row[i+1];
-
- unsigned char t1 = MIN(prev,next);
- unsigned char t2 = MIN(nextrow[i],prevrow[i]);
- *dst++ = MIN(curr,MIN(t1,t2));
- }
- unsigned char t1 = MIN(curr,next);
- unsigned char t2 = MIN(nextrow[width-1],prevrow[width-1]);
- *dst++ = MIN(t1,t2);
- }
-}
-
-/*
- Filters src image and saves it to dst, overwriting tmp in the process.
- Image must be width*height pixels high. Size controls radius of box blur.
- */
-LIQ_PRIVATE void liq_blur(unsigned char *src, unsigned char *tmp, unsigned char *dst, unsigned int width, unsigned int height, unsigned int size)
-{
- assert(size > 0);
- if (width < 2*size+1 || height < 2*size+1) {
- return;
- }
- transposing_1d_blur(src, tmp, width, height, size);
- transposing_1d_blur(tmp, dst, height, width, size);
-}
diff --git a/vendor/code.ivysaur.me/imagequant/blur.h b/vendor/code.ivysaur.me/imagequant/blur.h
deleted file mode 100644
index 06ae8cb..0000000
--- a/vendor/code.ivysaur.me/imagequant/blur.h
+++ /dev/null
@@ -1,4 +0,0 @@
-
-LIQ_PRIVATE void liq_blur(unsigned char *src, unsigned char *tmp, unsigned char *dst, unsigned int width, unsigned int height, unsigned int size);
-LIQ_PRIVATE void liq_max3(unsigned char *src, unsigned char *dst, unsigned int width, unsigned int height);
-LIQ_PRIVATE void liq_min3(unsigned char *src, unsigned char *dst, unsigned int width, unsigned int height);
diff --git a/vendor/code.ivysaur.me/imagequant/cflags_linux.go b/vendor/code.ivysaur.me/imagequant/cflags_linux.go
deleted file mode 100644
index df89f82..0000000
--- a/vendor/code.ivysaur.me/imagequant/cflags_linux.go
+++ /dev/null
@@ -1,9 +0,0 @@
-//+build !windows
-
-package imagequant
-
-/*
-#cgo CFLAGS: -O3 -fopenmp -fomit-frame-pointer -Wall -Wno-attributes -std=c99 -DNDEBUG -DUSE_SSE=1 -msse
-#cgo LDFLAGS: -lm -fopenmp -ldl
-*/
-import "C"
diff --git a/vendor/code.ivysaur.me/imagequant/cflags_windows.go b/vendor/code.ivysaur.me/imagequant/cflags_windows.go
deleted file mode 100644
index 0800274..0000000
--- a/vendor/code.ivysaur.me/imagequant/cflags_windows.go
+++ /dev/null
@@ -1,9 +0,0 @@
-//+build windows
-
-package imagequant
-
-/*
-#cgo CFLAGS: -O3 -fno-math-errno -fopenmp -funroll-loops -fomit-frame-pointer -Wall -Wno-attributes -std=c99 -DNDEBUG -DUSE_SSE=1 -msse -fexcess-precision=fast
-#cgo LDFLAGS: -fopenmp -static
-*/
-import "C"
\ No newline at end of file
diff --git a/vendor/code.ivysaur.me/imagequant/go.mod b/vendor/code.ivysaur.me/imagequant/go.mod
deleted file mode 100644
index 94eda2c..0000000
--- a/vendor/code.ivysaur.me/imagequant/go.mod
+++ /dev/null
@@ -1 +0,0 @@
-module code.ivysaur.me/imagequant
diff --git a/vendor/code.ivysaur.me/imagequant/imagequant.go b/vendor/code.ivysaur.me/imagequant/imagequant.go
deleted file mode 100644
index d121883..0000000
--- a/vendor/code.ivysaur.me/imagequant/imagequant.go
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
-Copyright (c) 2016, The go-imagequant author(s)
-
-Permission to use, copy, modify, and/or distribute this software for any purpose
-with or without fee is hereby granted, provided that the above copyright notice
-and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD TO
-THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
-IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
-OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
-ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-*/
-
-package imagequant
-
-import (
- "errors"
-)
-
-/*
-#include "libimagequant.h"
-
-const char* liqVersionString() {
- return LIQ_VERSION_STRING;
-}
-
-*/
-import "C"
-
-var (
- ErrQualityTooLow = errors.New("Quality too low")
- ErrValueOutOfRange = errors.New("Value out of range")
- ErrOutOfMemory = errors.New("Out of memory")
- ErrAborted = errors.New("Aborted")
- ErrBitmapNotAvailable = errors.New("Bitmap not available")
- ErrBufferTooSmall = errors.New("Buffer too small")
- ErrInvalidPointer = errors.New("Invalid pointer")
-
- ErrUseAfterFree = errors.New("Use after free")
-)
-
-func translateError(iqe C.liq_error) error {
- switch iqe {
- case C.LIQ_OK:
- return nil
- case (C.LIQ_QUALITY_TOO_LOW):
- return ErrQualityTooLow
- case (C.LIQ_VALUE_OUT_OF_RANGE):
- return ErrValueOutOfRange
- case (C.LIQ_OUT_OF_MEMORY):
- return ErrOutOfMemory
- case (C.LIQ_ABORTED):
- return ErrAborted
- case (C.LIQ_BITMAP_NOT_AVAILABLE):
- return ErrBitmapNotAvailable
- case (C.LIQ_BUFFER_TOO_SMALL):
- return ErrBufferTooSmall
- case (C.LIQ_INVALID_POINTER):
- return ErrInvalidPointer
- default:
- return errors.New("Unknown error")
- }
-}
-
-func GetLibraryVersion() int {
- return int(C.liq_version())
-}
-
-func GetLibraryVersionString() string {
- return C.GoString(C.liqVersionString())
-}
diff --git a/vendor/code.ivysaur.me/imagequant/kmeans.c b/vendor/code.ivysaur.me/imagequant/kmeans.c
deleted file mode 100644
index 7ee273d..0000000
--- a/vendor/code.ivysaur.me/imagequant/kmeans.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
-** © 2011-2016 by Kornel Lesiński.
-** See COPYRIGHT file for license.
-*/
-
-#include "libimagequant.h"
-#include "pam.h"
-#include "kmeans.h"
-#include "nearest.h"
-#include
-#include
-
-#ifdef _OPENMP
-#include
-#else
-#define omp_get_max_threads() 1
-#define omp_get_thread_num() 0
-#endif
-
-/*
- * K-Means iteration: new palette color is computed from weighted average of colors that map to that palette entry.
- */
-LIQ_PRIVATE void kmeans_init(const colormap *map, const unsigned int max_threads, kmeans_state average_color[])
-{
- memset(average_color, 0, sizeof(average_color[0])*(KMEANS_CACHE_LINE_GAP+map->colors)*max_threads);
-}
-
-LIQ_PRIVATE void kmeans_update_color(const f_pixel acolor, const float value, const colormap *map, unsigned int match, const unsigned int thread, kmeans_state average_color[])
-{
- match += thread * (KMEANS_CACHE_LINE_GAP+map->colors);
- average_color[match].a += acolor.a * value;
- average_color[match].r += acolor.r * value;
- average_color[match].g += acolor.g * value;
- average_color[match].b += acolor.b * value;
- average_color[match].total += value;
-}
-
-LIQ_PRIVATE void kmeans_finalize(colormap *map, const unsigned int max_threads, const kmeans_state average_color[])
-{
- for (unsigned int i=0; i < map->colors; i++) {
- double a=0, r=0, g=0, b=0, total=0;
-
- // Aggregate results from all threads
- for(unsigned int t=0; t < max_threads; t++) {
- const unsigned int offset = (KMEANS_CACHE_LINE_GAP+map->colors) * t + i;
-
- a += average_color[offset].a;
- r += average_color[offset].r;
- g += average_color[offset].g;
- b += average_color[offset].b;
- total += average_color[offset].total;
- }
-
- if (total && !map->palette[i].fixed) {
- map->palette[i].acolor = (f_pixel){
- .a = a / total,
- .r = r / total,
- .g = g / total,
- .b = b / total,
- };
- map->palette[i].popularity = total;
- }
- }
-}
-
-LIQ_PRIVATE double kmeans_do_iteration(histogram *hist, colormap *const map, kmeans_callback callback)
-{
- const unsigned int max_threads = omp_get_max_threads();
- LIQ_ARRAY(kmeans_state, average_color, (KMEANS_CACHE_LINE_GAP+map->colors) * max_threads);
- kmeans_init(map, max_threads, average_color);
- struct nearest_map *const n = nearest_init(map);
- hist_item *const achv = hist->achv;
- const int hist_size = hist->size;
-
- double total_diff=0;
- #pragma omp parallel for if (hist_size > 2000) \
- schedule(static) default(none) shared(average_color,callback) reduction(+:total_diff)
- for(int j=0; j < hist_size; j++) {
- float diff;
- unsigned int match = nearest_search(n, &achv[j].acolor, achv[j].tmp.likely_colormap_index, &diff);
- achv[j].tmp.likely_colormap_index = match;
- total_diff += diff * achv[j].perceptual_weight;
-
- kmeans_update_color(achv[j].acolor, achv[j].perceptual_weight, map, match, omp_get_thread_num(), average_color);
-
- if (callback) callback(&achv[j], diff);
- }
-
- nearest_free(n);
- kmeans_finalize(map, max_threads, average_color);
-
- return total_diff / hist->total_perceptual_weight;
-}
diff --git a/vendor/code.ivysaur.me/imagequant/kmeans.h b/vendor/code.ivysaur.me/imagequant/kmeans.h
deleted file mode 100644
index c51d7bb..0000000
--- a/vendor/code.ivysaur.me/imagequant/kmeans.h
+++ /dev/null
@@ -1,19 +0,0 @@
-
-#ifndef KMEANS_H
-#define KMEANS_H
-
-// Spread memory touched by different threads at least 64B apart which I assume is the cache line size. This should avoid memory write contention.
-#define KMEANS_CACHE_LINE_GAP ((64+sizeof(kmeans_state)-1)/sizeof(kmeans_state))
-
-typedef struct {
- double a, r, g, b, total;
-} kmeans_state;
-
-typedef void (*kmeans_callback)(hist_item *item, float diff);
-
-LIQ_PRIVATE void kmeans_init(const colormap *map, const unsigned int max_threads, kmeans_state state[]);
-LIQ_PRIVATE void kmeans_update_color(const f_pixel acolor, const float value, const colormap *map, unsigned int match, const unsigned int thread, kmeans_state average_color[]);
-LIQ_PRIVATE void kmeans_finalize(colormap *map, const unsigned int max_threads, const kmeans_state state[]);
-LIQ_PRIVATE double kmeans_do_iteration(histogram *hist, colormap *const map, kmeans_callback callback);
-
-#endif
diff --git a/vendor/code.ivysaur.me/imagequant/libimagequant.c b/vendor/code.ivysaur.me/imagequant/libimagequant.c
deleted file mode 100644
index 3506564..0000000
--- a/vendor/code.ivysaur.me/imagequant/libimagequant.c
+++ /dev/null
@@ -1,2159 +0,0 @@
-/*
-** © 2009-2018 by Kornel Lesiński.
-** © 1989, 1991 by Jef Poskanzer.
-** © 1997, 2000, 2002 by Greg Roelofs; based on an idea by Stefan Schneider.
-**
-** See COPYRIGHT file for license.
-*/
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#if !(defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199900L) && !(defined(_MSC_VER) && _MSC_VER >= 1800)
-#error "This program requires C99, e.g. -std=c99 switch in GCC or it requires MSVC 18.0 or higher."
-#error "Ignore torrent of syntax errors that may follow. It's only because compiler is set to use too old C version."
-#endif
-
-#ifdef _OPENMP
-#include
-#define LIQ_TEMP_ROW_WIDTH(img_width) (((img_width) | 15) + 1) /* keep alignment & leave space between rows to avoid cache line contention */
-#else
-#define LIQ_TEMP_ROW_WIDTH(img_width) (img_width)
-#define omp_get_max_threads() 1
-#define omp_get_thread_num() 0
-#endif
-
-#include "libimagequant.h"
-
-#include "pam.h"
-#include "mediancut.h"
-#include "nearest.h"
-#include "blur.h"
-#include "kmeans.h"
-
-#define LIQ_HIGH_MEMORY_LIMIT (1<<26) /* avoid allocating buffers larger than 64MB */
-
-// each structure has a pointer as a unique identifier that allows type checking at run time
-static const char liq_attr_magic[] = "liq_attr";
-static const char liq_image_magic[] = "liq_image";
-static const char liq_result_magic[] = "liq_result";
-static const char liq_histogram_magic[] = "liq_histogram";
-static const char liq_remapping_result_magic[] = "liq_remapping_result";
-static const char liq_freed_magic[] = "free";
-#define CHECK_STRUCT_TYPE(attr, kind) liq_crash_if_invalid_handle_pointer_given((const liq_attr*)attr, kind ## _magic)
-#define CHECK_USER_POINTER(ptr) liq_crash_if_invalid_pointer_given(ptr)
-
-struct liq_attr {
- const char *magic_header;
- void* (*malloc)(size_t);
- void (*free)(void*);
-
- double target_mse, max_mse, kmeans_iteration_limit;
- float min_opaque_val;
- unsigned int max_colors, max_histogram_entries;
- unsigned int min_posterization_output /* user setting */, min_posterization_input /* speed setting */;
- unsigned int kmeans_iterations, feedback_loop_trials;
- bool last_index_transparent, use_contrast_maps;
- unsigned char use_dither_map;
- unsigned char speed;
-
- unsigned char progress_stage1, progress_stage2, progress_stage3;
- liq_progress_callback_function *progress_callback;
- void *progress_callback_user_info;
-
- liq_log_callback_function *log_callback;
- void *log_callback_user_info;
- liq_log_flush_callback_function *log_flush_callback;
- void *log_flush_callback_user_info;
-};
-
-struct liq_image {
- const char *magic_header;
- void* (*malloc)(size_t);
- void (*free)(void*);
-
- f_pixel *f_pixels;
- rgba_pixel **rows;
- double gamma;
- unsigned int width, height;
- unsigned char *importance_map, *edges, *dither_map;
- rgba_pixel *pixels, *temp_row;
- f_pixel *temp_f_row;
- liq_image_get_rgba_row_callback *row_callback;
- void *row_callback_user_info;
- liq_image *background;
- float min_opaque_val;
- f_pixel fixed_colors[256];
- unsigned short fixed_colors_count;
- bool free_pixels, free_rows, free_rows_internal;
-};
-
-typedef struct liq_remapping_result {
- const char *magic_header;
- void* (*malloc)(size_t);
- void (*free)(void*);
-
- unsigned char *pixels;
- colormap *palette;
- liq_progress_callback_function *progress_callback;
- void *progress_callback_user_info;
-
- liq_palette int_palette;
- double gamma, palette_error;
- float dither_level;
- unsigned char use_dither_map;
- unsigned char progress_stage1;
-} liq_remapping_result;
-
-struct liq_result {
- const char *magic_header;
- void* (*malloc)(size_t);
- void (*free)(void*);
-
- liq_remapping_result *remapping;
- colormap *palette;
- liq_progress_callback_function *progress_callback;
- void *progress_callback_user_info;
-
- liq_palette int_palette;
- float dither_level;
- double gamma, palette_error;
- int min_posterization_output;
- unsigned char use_dither_map;
-};
-
-struct liq_histogram {
- const char *magic_header;
- void* (*malloc)(size_t);
- void (*free)(void*);
-
- struct acolorhash_table *acht;
- double gamma;
- f_pixel fixed_colors[256];
- unsigned short fixed_colors_count;
- unsigned short ignorebits;
- bool had_image_added;
-};
-
-static void modify_alpha(liq_image *input_image, rgba_pixel *const row_pixels) LIQ_NONNULL;
-static void contrast_maps(liq_image *image) LIQ_NONNULL;
-static liq_error finalize_histogram(liq_histogram *input_hist, liq_attr *options, histogram **hist_output) LIQ_NONNULL;
-static const rgba_pixel *liq_image_get_row_rgba(liq_image *input_image, unsigned int row) LIQ_NONNULL;
-static bool liq_image_get_row_f_init(liq_image *img) LIQ_NONNULL;
-static const f_pixel *liq_image_get_row_f(liq_image *input_image, unsigned int row) LIQ_NONNULL;
-static void liq_remapping_result_destroy(liq_remapping_result *result) LIQ_NONNULL;
-static liq_error pngquant_quantize(histogram *hist, const liq_attr *options, const int fixed_colors_count, const f_pixel fixed_colors[], const double gamma, bool fixed_result_colors, liq_result **) LIQ_NONNULL;
-static liq_error liq_histogram_quantize_internal(liq_histogram *input_hist, liq_attr *attr, bool fixed_result_colors, liq_result **result_output) LIQ_NONNULL;
-
-LIQ_NONNULL static void liq_verbose_printf(const liq_attr *context, const char *fmt, ...)
-{
- if (context->log_callback) {
- va_list va;
- va_start(va, fmt);
- int required_space = vsnprintf(NULL, 0, fmt, va)+1; // +\0
- va_end(va);
-
- LIQ_ARRAY(char, buf, required_space);
- va_start(va, fmt);
- vsnprintf(buf, required_space, fmt, va);
- va_end(va);
-
- context->log_callback(context, buf, context->log_callback_user_info);
- }
-}
-
-LIQ_NONNULL inline static void verbose_print(const liq_attr *attr, const char *msg)
-{
- if (attr->log_callback) {
- attr->log_callback(attr, msg, attr->log_callback_user_info);
- }
-}
-
-LIQ_NONNULL static void liq_verbose_printf_flush(liq_attr *attr)
-{
- if (attr->log_flush_callback) {
- attr->log_flush_callback(attr, attr->log_flush_callback_user_info);
- }
-}
-
-LIQ_NONNULL static bool liq_progress(const liq_attr *attr, const float percent)
-{
- return attr->progress_callback && !attr->progress_callback(percent, attr->progress_callback_user_info);
-}
-
-LIQ_NONNULL static bool liq_remap_progress(const liq_remapping_result *quant, const float percent)
-{
- return quant->progress_callback && !quant->progress_callback(percent, quant->progress_callback_user_info);
-}
-
-#if USE_SSE
-inline static bool is_sse_available()
-{
-#if (defined(__x86_64__) || defined(__amd64) || defined(_WIN64))
- return true;
-#elif _MSC_VER
- int info[4];
- __cpuid(info, 1);
- /* bool is implemented as a built-in type of size 1 in MSVC */
- return info[3] & (1<<26) ? true : false;
-#else
- int a,b,c,d;
- cpuid(1, a, b, c, d);
- return d & (1<<25); // edx bit 25 is set when SSE is present
-#endif
-}
-#endif
-
-/* make it clear in backtrace when user-supplied handle points to invalid memory */
-NEVER_INLINE LIQ_EXPORT bool liq_crash_if_invalid_handle_pointer_given(const liq_attr *user_supplied_pointer, const char *const expected_magic_header);
-LIQ_EXPORT bool liq_crash_if_invalid_handle_pointer_given(const liq_attr *user_supplied_pointer, const char *const expected_magic_header)
-{
- if (!user_supplied_pointer) {
- return false;
- }
-
- if (user_supplied_pointer->magic_header == liq_freed_magic) {
- fprintf(stderr, "%s used after being freed", expected_magic_header);
- // this is not normal error handling, this is programmer error that should crash the program.
- // program cannot safely continue if memory has been used after it's been freed.
- // abort() is nasty, but security vulnerability may be worse.
- abort();
- }
-
- return user_supplied_pointer->magic_header == expected_magic_header;
-}
-
-NEVER_INLINE LIQ_EXPORT bool liq_crash_if_invalid_pointer_given(const void *pointer);
-LIQ_EXPORT bool liq_crash_if_invalid_pointer_given(const void *pointer)
-{
- if (!pointer) {
- return false;
- }
- // Force a read from the given (potentially invalid) memory location in order to check early whether this crashes the program or not.
- // It doesn't matter what value is read, the code here is just to shut the compiler up about unused read.
- char test_access = *((volatile char *)pointer);
- return test_access || true;
-}
-
-LIQ_NONNULL static void liq_log_error(const liq_attr *attr, const char *msg)
-{
- if (!CHECK_STRUCT_TYPE(attr, liq_attr)) return;
- liq_verbose_printf(attr, " error: %s", msg);
-}
-
-static double quality_to_mse(long quality)
-{
- if (quality == 0) {
- return MAX_DIFF;
- }
- if (quality == 100) {
- return 0;
- }
-
- // curve fudged to be roughly similar to quality of libjpeg
- // except lowest 10 for really low number of colors
- const double extra_low_quality_fudge = MAX(0,0.016/(0.001+quality) - 0.001);
- return extra_low_quality_fudge + 2.5/pow(210.0 + quality, 1.2) * (100.1-quality)/100.0;
-}
-
-static unsigned int mse_to_quality(double mse)
-{
- for(int i=100; i > 0; i--) {
- if (mse <= quality_to_mse(i) + 0.000001) { // + epsilon for floating point errors
- return i;
- }
- }
- return 0;
-}
-
-/** internally MSE is a sum of all channels with pixels 0..1 range,
- but other software gives per-RGB-channel MSE for 0..255 range */
-static double mse_to_standard_mse(double mse) {
- return mse * 65536.0/6.0;
-}
-
-LIQ_EXPORT LIQ_NONNULL liq_error liq_set_quality(liq_attr* attr, int minimum, int target)
-{
- if (!CHECK_STRUCT_TYPE(attr, liq_attr)) return LIQ_INVALID_POINTER;
- if (target < 0 || target > 100 || target < minimum || minimum < 0) return LIQ_VALUE_OUT_OF_RANGE;
-
- attr->target_mse = quality_to_mse(target);
- attr->max_mse = quality_to_mse(minimum);
- return LIQ_OK;
-}
-
-LIQ_EXPORT LIQ_NONNULL int liq_get_min_quality(const liq_attr *attr)
-{
- if (!CHECK_STRUCT_TYPE(attr, liq_attr)) return -1;
- return mse_to_quality(attr->max_mse);
-}
-
-LIQ_EXPORT LIQ_NONNULL int liq_get_max_quality(const liq_attr *attr)
-{
- if (!CHECK_STRUCT_TYPE(attr, liq_attr)) return -1;
- return mse_to_quality(attr->target_mse);
-}
-
-
-LIQ_EXPORT LIQ_NONNULL liq_error liq_set_max_colors(liq_attr* attr, int colors)
-{
- if (!CHECK_STRUCT_TYPE(attr, liq_attr)) return LIQ_INVALID_POINTER;
- if (colors < 2 || colors > 256) return LIQ_VALUE_OUT_OF_RANGE;
-
- attr->max_colors = colors;
- return LIQ_OK;
-}
-
-LIQ_EXPORT LIQ_NONNULL int liq_get_max_colors(const liq_attr *attr)
-{
- if (!CHECK_STRUCT_TYPE(attr, liq_attr)) return -1;
-
- return attr->max_colors;
-}
-
-LIQ_EXPORT LIQ_NONNULL liq_error liq_set_min_posterization(liq_attr *attr, int bits)
-{
- if (!CHECK_STRUCT_TYPE(attr, liq_attr)) return LIQ_INVALID_POINTER;
- if (bits < 0 || bits > 4) return LIQ_VALUE_OUT_OF_RANGE;
-
- attr->min_posterization_output = bits;
- return LIQ_OK;
-}
-
-LIQ_EXPORT LIQ_NONNULL int liq_get_min_posterization(const liq_attr *attr)
-{
- if (!CHECK_STRUCT_TYPE(attr, liq_attr)) return -1;
-
- return attr->min_posterization_output;
-}
-
-LIQ_EXPORT LIQ_NONNULL liq_error liq_set_speed(liq_attr* attr, int speed)
-{
- if (!CHECK_STRUCT_TYPE(attr, liq_attr)) return LIQ_INVALID_POINTER;
- if (speed < 1 || speed > 10) return LIQ_VALUE_OUT_OF_RANGE;
-
- unsigned int iterations = MAX(8-speed, 0);
- iterations += iterations * iterations/2;
- attr->kmeans_iterations = iterations;
- attr->kmeans_iteration_limit = 1.0/(double)(1<<(23-speed));
- attr->feedback_loop_trials = MAX(56-9*speed, 0);
-
- attr->max_histogram_entries = (1<<17) + (1<<18)*(10-speed);
- attr->min_posterization_input = (speed >= 8) ? 1 : 0;
- attr->use_dither_map = (speed <= (omp_get_max_threads() > 1 ? 7 : 5)); // parallelized dither map might speed up floyd remapping
- if (attr->use_dither_map && speed < 3) {
- attr->use_dither_map = 2; // always
- }
- attr->use_contrast_maps = (speed <= 7) || attr->use_dither_map;
- attr->speed = speed;
-
- attr->progress_stage1 = attr->use_contrast_maps ? 20 : 8;
- if (attr->feedback_loop_trials < 2) {
- attr->progress_stage1 += 30;
- }
- attr->progress_stage3 = 50 / (1+speed);
- attr->progress_stage2 = 100 - attr->progress_stage1 - attr->progress_stage3;
- return LIQ_OK;
-}
-
-LIQ_EXPORT LIQ_NONNULL int liq_get_speed(const liq_attr *attr)
-{
- if (!CHECK_STRUCT_TYPE(attr, liq_attr)) return -1;
-
- return attr->speed;
-}
-
-LIQ_EXPORT LIQ_NONNULL liq_error liq_set_output_gamma(liq_result* res, double gamma)
-{
- if (!CHECK_STRUCT_TYPE(res, liq_result)) return LIQ_INVALID_POINTER;
- if (gamma <= 0 || gamma >= 1.0) return LIQ_VALUE_OUT_OF_RANGE;
-
- if (res->remapping) {
- liq_remapping_result_destroy(res->remapping);
- res->remapping = NULL;
- }
-
- res->gamma = gamma;
- return LIQ_OK;
-}
-
-LIQ_EXPORT LIQ_NONNULL liq_error liq_set_min_opacity(liq_attr* attr, int min)
-{
- if (!CHECK_STRUCT_TYPE(attr, liq_attr)) return LIQ_INVALID_POINTER;
- if (min < 0 || min > 255) return LIQ_VALUE_OUT_OF_RANGE;
-
- attr->min_opaque_val = (double)min/255.0;
- return LIQ_OK;
-}
-
-LIQ_EXPORT LIQ_NONNULL int liq_get_min_opacity(const liq_attr *attr)
-{
- if (!CHECK_STRUCT_TYPE(attr, liq_attr)) return -1;
-
- return MIN(255.f, 256.f * attr->min_opaque_val);
-}
-
-LIQ_EXPORT LIQ_NONNULL void liq_set_last_index_transparent(liq_attr* attr, int is_last)
-{
- if (!CHECK_STRUCT_TYPE(attr, liq_attr)) return;
-
- attr->last_index_transparent = !!is_last;
-}
-
-LIQ_EXPORT void liq_attr_set_progress_callback(liq_attr *attr, liq_progress_callback_function *callback, void *user_info)
-{
- if (!CHECK_STRUCT_TYPE(attr, liq_attr)) return;
-
- attr->progress_callback = callback;
- attr->progress_callback_user_info = user_info;
-}
-
-LIQ_EXPORT void liq_result_set_progress_callback(liq_result *result, liq_progress_callback_function *callback, void *user_info)
-{
- if (!CHECK_STRUCT_TYPE(result, liq_result)) return;
-
- result->progress_callback = callback;
- result->progress_callback_user_info = user_info;
-}
-
-LIQ_EXPORT void liq_set_log_callback(liq_attr *attr, liq_log_callback_function *callback, void* user_info)
-{
- if (!CHECK_STRUCT_TYPE(attr, liq_attr)) return;
-
- liq_verbose_printf_flush(attr);
- attr->log_callback = callback;
- attr->log_callback_user_info = user_info;
-}
-
-LIQ_EXPORT void liq_set_log_flush_callback(liq_attr *attr, liq_log_flush_callback_function *callback, void* user_info)
-{
- if (!CHECK_STRUCT_TYPE(attr, liq_attr)) return;
-
- attr->log_flush_callback = callback;
- attr->log_flush_callback_user_info = user_info;
-}
-
-LIQ_EXPORT liq_attr* liq_attr_create()
-{
- return liq_attr_create_with_allocator(NULL, NULL);
-}
-
-LIQ_EXPORT LIQ_NONNULL void liq_attr_destroy(liq_attr *attr)
-{
- if (!CHECK_STRUCT_TYPE(attr, liq_attr)) {
- return;
- }
-
- liq_verbose_printf_flush(attr);
-
- attr->magic_header = liq_freed_magic;
- attr->free(attr);
-}
-
-LIQ_EXPORT LIQ_NONNULL liq_attr* liq_attr_copy(const liq_attr *orig)
-{
- if (!CHECK_STRUCT_TYPE(orig, liq_attr)) {
- return NULL;
- }
-
- liq_attr *attr = orig->malloc(sizeof(liq_attr));
- if (!attr) return NULL;
- *attr = *orig;
- return attr;
-}
-
-static void *liq_aligned_malloc(size_t size)
-{
- unsigned char *ptr = malloc(size + 16);
- if (!ptr) {
- return NULL;
- }
-
- uintptr_t offset = 16 - ((uintptr_t)ptr & 15); // also reserves 1 byte for ptr[-1]
- ptr += offset;
- assert(0 == (((uintptr_t)ptr) & 15));
- ptr[-1] = offset ^ 0x59; // store how much pointer was shifted to get the original for free()
- return ptr;
-}
-
-LIQ_NONNULL static void liq_aligned_free(void *inptr)
-{
- unsigned char *ptr = inptr;
- size_t offset = ptr[-1] ^ 0x59;
- assert(offset > 0 && offset <= 16);
- free(ptr - offset);
-}
-
-LIQ_EXPORT liq_attr* liq_attr_create_with_allocator(void* (*custom_malloc)(size_t), void (*custom_free)(void*))
-{
-#if USE_SSE
- if (!is_sse_available()) {
- return NULL;
- }
-#endif
- if (!custom_malloc && !custom_free) {
- custom_malloc = liq_aligned_malloc;
- custom_free = liq_aligned_free;
- } else if (!custom_malloc != !custom_free) {
- return NULL; // either specify both or none
- }
-
- liq_attr *attr = custom_malloc(sizeof(liq_attr));
- if (!attr) return NULL;
- *attr = (liq_attr) {
- .magic_header = liq_attr_magic,
- .malloc = custom_malloc,
- .free = custom_free,
- .max_colors = 256,
- .min_opaque_val = 1, // whether preserve opaque colors for IE (1.0=no, does not affect alpha)
- .last_index_transparent = false, // puts transparent color at last index. This is workaround for blu-ray subtitles.
- .target_mse = 0,
- .max_mse = MAX_DIFF,
- };
- liq_set_speed(attr, 4);
- return attr;
-}
-
-LIQ_EXPORT LIQ_NONNULL liq_error liq_image_add_fixed_color(liq_image *img, liq_color color)
-{
- if (!CHECK_STRUCT_TYPE(img, liq_image)) return LIQ_INVALID_POINTER;
- if (img->fixed_colors_count > 255) return LIQ_UNSUPPORTED;
-
- float gamma_lut[256];
- to_f_set_gamma(gamma_lut, img->gamma);
- img->fixed_colors[img->fixed_colors_count++] = rgba_to_f(gamma_lut, (rgba_pixel){
- .r = color.r,
- .g = color.g,
- .b = color.b,
- .a = color.a,
- });
- return LIQ_OK;
-}
-
-LIQ_NONNULL static liq_error liq_histogram_add_fixed_color_f(liq_histogram *hist, f_pixel color)
-{
- if (hist->fixed_colors_count > 255) return LIQ_UNSUPPORTED;
-
- hist->fixed_colors[hist->fixed_colors_count++] = color;
- return LIQ_OK;
-}
-
-LIQ_EXPORT LIQ_NONNULL liq_error liq_histogram_add_fixed_color(liq_histogram *hist, liq_color color, double gamma)
-{
- if (!CHECK_STRUCT_TYPE(hist, liq_histogram)) return LIQ_INVALID_POINTER;
-
- float gamma_lut[256];
- to_f_set_gamma(gamma_lut, gamma ? gamma : 0.45455);
- const f_pixel px = rgba_to_f(gamma_lut, (rgba_pixel){
- .r = color.r,
- .g = color.g,
- .b = color.b,
- .a = color.a,
- });
- return liq_histogram_add_fixed_color_f(hist, px);
-}
-
-LIQ_NONNULL static bool liq_image_use_low_memory(liq_image *img)
-{
- img->temp_f_row = img->malloc(sizeof(img->f_pixels[0]) * LIQ_TEMP_ROW_WIDTH(img->width) * omp_get_max_threads());
- return img->temp_f_row != NULL;
-}
-
-LIQ_NONNULL static bool liq_image_should_use_low_memory(liq_image *img, const bool low_memory_hint)
-{
- return img->width * img->height > (low_memory_hint ? LIQ_HIGH_MEMORY_LIMIT/8 : LIQ_HIGH_MEMORY_LIMIT) / sizeof(f_pixel); // Watch out for integer overflow
-}
-
-static liq_image *liq_image_create_internal(const liq_attr *attr, rgba_pixel* rows[], liq_image_get_rgba_row_callback *row_callback, void *row_callback_user_info, int width, int height, double gamma)
-{
- if (gamma < 0 || gamma > 1.0) {
- liq_log_error(attr, "gamma must be >= 0 and <= 1 (try 1/gamma instead)");
- return NULL;
- }
-
- if (!rows && !row_callback) {
- liq_log_error(attr, "missing row data");
- return NULL;
- }
-
- liq_image *img = attr->malloc(sizeof(liq_image));
- if (!img) return NULL;
- *img = (liq_image){
- .magic_header = liq_image_magic,
- .malloc = attr->malloc,
- .free = attr->free,
- .width = width, .height = height,
- .gamma = gamma ? gamma : 0.45455,
- .rows = rows,
- .row_callback = row_callback,
- .row_callback_user_info = row_callback_user_info,
- .min_opaque_val = attr->min_opaque_val,
- };
-
- if (!rows || attr->min_opaque_val < 1.f) {
- img->temp_row = attr->malloc(sizeof(img->temp_row[0]) * LIQ_TEMP_ROW_WIDTH(width) * omp_get_max_threads());
- if (!img->temp_row) return NULL;
- }
-
- // if image is huge or converted pixels are not likely to be reused then don't cache converted pixels
- if (liq_image_should_use_low_memory(img, !img->temp_row && !attr->use_contrast_maps && !attr->use_dither_map)) {
- verbose_print(attr, " conserving memory");
- if (!liq_image_use_low_memory(img)) return NULL;
- }
-
- if (img->min_opaque_val < 1.f) {
- verbose_print(attr, " Working around IE6 bug by making image less transparent...");
- }
-
- return img;
-}
-
-LIQ_EXPORT LIQ_NONNULL liq_error liq_image_set_memory_ownership(liq_image *img, int ownership_flags)
-{
- if (!CHECK_STRUCT_TYPE(img, liq_image)) return LIQ_INVALID_POINTER;
- if (!img->rows || !ownership_flags || (ownership_flags & ~(LIQ_OWN_ROWS|LIQ_OWN_PIXELS))) {
- return LIQ_VALUE_OUT_OF_RANGE;
- }
-
- if (ownership_flags & LIQ_OWN_ROWS) {
- if (img->free_rows_internal) return LIQ_VALUE_OUT_OF_RANGE;
- img->free_rows = true;
- }
-
- if (ownership_flags & LIQ_OWN_PIXELS) {
- img->free_pixels = true;
- if (!img->pixels) {
- // for simplicity of this API there's no explicit bitmap argument,
- // so the row with the lowest address is assumed to be at the start of the bitmap
- img->pixels = img->rows[0];
- for(unsigned int i=1; i < img->height; i++) {
- img->pixels = MIN(img->pixels, img->rows[i]);
- }
- }
- }
-
- return LIQ_OK;
-}
-
-LIQ_NONNULL static void liq_image_free_maps(liq_image *input_image);
-LIQ_NONNULL static void liq_image_free_importance_map(liq_image *input_image);
-
-LIQ_EXPORT LIQ_NONNULL liq_error liq_image_set_importance_map(liq_image *img, unsigned char importance_map[], size_t buffer_size, enum liq_ownership ownership) {
- if (!CHECK_STRUCT_TYPE(img, liq_image)) return LIQ_INVALID_POINTER;
- if (!CHECK_USER_POINTER(importance_map)) return LIQ_INVALID_POINTER;
-
- const size_t required_size = img->width * img->height;
- if (buffer_size < required_size) {
- return LIQ_BUFFER_TOO_SMALL;
- }
-
- if (ownership == LIQ_COPY_PIXELS) {
- unsigned char *tmp = img->malloc(required_size);
- if (!tmp) {
- return LIQ_OUT_OF_MEMORY;
- }
- memcpy(tmp, importance_map, required_size);
- importance_map = tmp;
- } else if (ownership != LIQ_OWN_PIXELS) {
- return LIQ_UNSUPPORTED;
- }
-
- liq_image_free_importance_map(img);
- img->importance_map = importance_map;
-
- return LIQ_OK;
-}
-
-LIQ_EXPORT LIQ_NONNULL liq_error liq_image_set_background(liq_image *img, liq_image *background)
-{
- if (!CHECK_STRUCT_TYPE(img, liq_image)) return LIQ_INVALID_POINTER;
- if (!CHECK_STRUCT_TYPE(background, liq_image)) return LIQ_INVALID_POINTER;
-
- if (background->background) {
- return LIQ_UNSUPPORTED;
- }
- if (img->width != background->width || img->height != background->height) {
- return LIQ_BUFFER_TOO_SMALL;
- }
-
- if (img->background) {
- liq_image_destroy(img->background);
- }
-
- img->background = background;
- liq_image_free_maps(img); // Force them to be re-analyzed with the background
-
- return LIQ_OK;
-}
-
-LIQ_NONNULL static bool check_image_size(const liq_attr *attr, const int width, const int height)
-{
- if (!CHECK_STRUCT_TYPE(attr, liq_attr)) {
- return false;
- }
-
- if (width <= 0 || height <= 0) {
- liq_log_error(attr, "width and height must be > 0");
- return false;
- }
-
- if (width > INT_MAX/sizeof(rgba_pixel)/height || width > INT_MAX/16/sizeof(f_pixel) || height > INT_MAX/sizeof(size_t)) {
- liq_log_error(attr, "image too large");
- return false;
- }
- return true;
-}
-
-LIQ_EXPORT liq_image *liq_image_create_custom(const liq_attr *attr, liq_image_get_rgba_row_callback *row_callback, void* user_info, int width, int height, double gamma)
-{
- if (!check_image_size(attr, width, height)) {
- return NULL;
- }
- return liq_image_create_internal(attr, NULL, row_callback, user_info, width, height, gamma);
-}
-
-LIQ_EXPORT liq_image *liq_image_create_rgba_rows(const liq_attr *attr, void *const rows[], int width, int height, double gamma)
-{
- if (!check_image_size(attr, width, height)) {
- return NULL;
- }
-
- for(int i=0; i < height; i++) {
- if (!CHECK_USER_POINTER(rows+i) || !CHECK_USER_POINTER(rows[i])) {
- liq_log_error(attr, "invalid row pointers");
- return NULL;
- }
- }
- return liq_image_create_internal(attr, (rgba_pixel**)rows, NULL, NULL, width, height, gamma);
-}
-
-LIQ_EXPORT LIQ_NONNULL liq_image *liq_image_create_rgba(const liq_attr *attr, const void* bitmap, int width, int height, double gamma)
-{
- if (!check_image_size(attr, width, height)) {
- return NULL;
- }
- if (!CHECK_USER_POINTER(bitmap)) {
- liq_log_error(attr, "invalid bitmap pointer");
- return NULL;
- }
-
- rgba_pixel *const pixels = (rgba_pixel *const)bitmap;
- rgba_pixel **rows = attr->malloc(sizeof(rows[0])*height);
- if (!rows) return NULL;
-
- for(int i=0; i < height; i++) {
- rows[i] = pixels + width * i;
- }
-
- liq_image *image = liq_image_create_internal(attr, rows, NULL, NULL, width, height, gamma);
- if (!image) {
- attr->free(rows);
- return NULL;
- }
- image->free_rows = true;
- image->free_rows_internal = true;
- return image;
-}
-
-NEVER_INLINE LIQ_EXPORT void liq_executing_user_callback(liq_image_get_rgba_row_callback *callback, liq_color *temp_row, int row, int width, void *user_info);
-LIQ_EXPORT void liq_executing_user_callback(liq_image_get_rgba_row_callback *callback, liq_color *temp_row, int row, int width, void *user_info)
-{
- assert(callback);
- assert(temp_row);
- callback(temp_row, row, width, user_info);
-}
-
-LIQ_NONNULL inline static bool liq_image_has_rgba_pixels(const liq_image *img)
-{
- if (!CHECK_STRUCT_TYPE(img, liq_image)) {
- return false;
- }
- return img->rows || (img->temp_row && img->row_callback);
-}
-
-LIQ_NONNULL inline static bool liq_image_can_use_rgba_rows(const liq_image *img)
-{
- assert(liq_image_has_rgba_pixels(img));
-
- const bool iebug = img->min_opaque_val < 1.f;
- return (img->rows && !iebug);
-}
-
-LIQ_NONNULL static const rgba_pixel *liq_image_get_row_rgba(liq_image *img, unsigned int row)
-{
- if (liq_image_can_use_rgba_rows(img)) {
- return img->rows[row];
- }
-
- assert(img->temp_row);
- rgba_pixel *temp_row = img->temp_row + LIQ_TEMP_ROW_WIDTH(img->width) * omp_get_thread_num();
- if (img->rows) {
- memcpy(temp_row, img->rows[row], img->width * sizeof(temp_row[0]));
- } else {
- liq_executing_user_callback(img->row_callback, (liq_color*)temp_row, row, img->width, img->row_callback_user_info);
- }
-
- if (img->min_opaque_val < 1.f) modify_alpha(img, temp_row);
- return temp_row;
-}
-
-LIQ_NONNULL static void convert_row_to_f(liq_image *img, f_pixel *row_f_pixels, const unsigned int row, const float gamma_lut[])
-{
- assert(row_f_pixels);
- assert(!USE_SSE || 0 == ((uintptr_t)row_f_pixels & 15));
-
- const rgba_pixel *const row_pixels = liq_image_get_row_rgba(img, row);
-
- for(unsigned int col=0; col < img->width; col++) {
- row_f_pixels[col] = rgba_to_f(gamma_lut, row_pixels[col]);
- }
-}
-
-LIQ_NONNULL static bool liq_image_get_row_f_init(liq_image *img)
-{
- assert(omp_get_thread_num() == 0);
- if (img->f_pixels) {
- return true;
- }
- if (!liq_image_should_use_low_memory(img, false)) {
- img->f_pixels = img->malloc(sizeof(img->f_pixels[0]) * img->width * img->height);
- }
- if (!img->f_pixels) {
- return liq_image_use_low_memory(img);
- }
-
- if (!liq_image_has_rgba_pixels(img)) {
- return false;
- }
-
- float gamma_lut[256];
- to_f_set_gamma(gamma_lut, img->gamma);
- for(unsigned int i=0; i < img->height; i++) {
- convert_row_to_f(img, &img->f_pixels[i*img->width], i, gamma_lut);
- }
- return true;
-}
-
-LIQ_NONNULL static const f_pixel *liq_image_get_row_f(liq_image *img, unsigned int row)
-{
- if (!img->f_pixels) {
- assert(img->temp_f_row); // init should have done that
- float gamma_lut[256];
- to_f_set_gamma(gamma_lut, img->gamma);
- f_pixel *row_for_thread = img->temp_f_row + LIQ_TEMP_ROW_WIDTH(img->width) * omp_get_thread_num();
- convert_row_to_f(img, row_for_thread, row, gamma_lut);
- return row_for_thread;
- }
- return img->f_pixels + img->width * row;
-}
-
-LIQ_EXPORT LIQ_NONNULL int liq_image_get_width(const liq_image *input_image)
-{
- if (!CHECK_STRUCT_TYPE(input_image, liq_image)) return -1;
- return input_image->width;
-}
-
-LIQ_EXPORT LIQ_NONNULL int liq_image_get_height(const liq_image *input_image)
-{
- if (!CHECK_STRUCT_TYPE(input_image, liq_image)) return -1;
- return input_image->height;
-}
-
-typedef void free_func(void*);
-
-LIQ_NONNULL static free_func *get_default_free_func(liq_image *img)
-{
- // When default allocator is used then user-supplied pointers must be freed with free()
- if (img->free_rows_internal || img->free != liq_aligned_free) {
- return img->free;
- }
- return free;
-}
-
-LIQ_NONNULL static void liq_image_free_rgba_source(liq_image *input_image)
-{
- if (input_image->free_pixels && input_image->pixels) {
- get_default_free_func(input_image)(input_image->pixels);
- input_image->pixels = NULL;
- }
-
- if (input_image->free_rows && input_image->rows) {
- get_default_free_func(input_image)(input_image->rows);
- input_image->rows = NULL;
- }
-}
-
-LIQ_NONNULL static void liq_image_free_importance_map(liq_image *input_image) {
- if (input_image->importance_map) {
- input_image->free(input_image->importance_map);
- input_image->importance_map = NULL;
- }
-}
-
-LIQ_NONNULL static void liq_image_free_maps(liq_image *input_image) {
- liq_image_free_importance_map(input_image);
-
- if (input_image->edges) {
- input_image->free(input_image->edges);
- input_image->edges = NULL;
- }
-
- if (input_image->dither_map) {
- input_image->free(input_image->dither_map);
- input_image->dither_map = NULL;
- }
-}
-
-LIQ_EXPORT LIQ_NONNULL void liq_image_destroy(liq_image *input_image)
-{
- if (!CHECK_STRUCT_TYPE(input_image, liq_image)) return;
-
- liq_image_free_rgba_source(input_image);
-
- liq_image_free_maps(input_image);
-
- if (input_image->f_pixels) {
- input_image->free(input_image->f_pixels);
- }
-
- if (input_image->temp_row) {
- input_image->free(input_image->temp_row);
- }
-
- if (input_image->temp_f_row) {
- input_image->free(input_image->temp_f_row);
- }
-
- if (input_image->background) {
- liq_image_destroy(input_image->background);
- }
-
- input_image->magic_header = liq_freed_magic;
- input_image->free(input_image);
-}
-
-LIQ_EXPORT liq_histogram* liq_histogram_create(const liq_attr* attr)
-{
- if (!CHECK_STRUCT_TYPE(attr, liq_attr)) {
- return NULL;
- }
-
- liq_histogram *hist = attr->malloc(sizeof(liq_histogram));
- if (!hist) return NULL;
- *hist = (liq_histogram) {
- .magic_header = liq_histogram_magic,
- .malloc = attr->malloc,
- .free = attr->free,
-
- .ignorebits = MAX(attr->min_posterization_output, attr->min_posterization_input),
- };
- return hist;
-}
-
-LIQ_EXPORT LIQ_NONNULL void liq_histogram_destroy(liq_histogram *hist)
-{
- if (!CHECK_STRUCT_TYPE(hist, liq_histogram)) return;
- hist->magic_header = liq_freed_magic;
-
- pam_freeacolorhash(hist->acht);
- hist->free(hist);
-}
-
-LIQ_EXPORT LIQ_NONNULL liq_result *liq_quantize_image(liq_attr *attr, liq_image *img)
-{
- liq_result *res;
- if (LIQ_OK != liq_image_quantize(img, attr, &res)) {
- return NULL;
- }
- return res;
-}
-
-LIQ_EXPORT LIQ_NONNULL liq_error liq_image_quantize(liq_image *const img, liq_attr *const attr, liq_result **result_output)
-{
- if (!CHECK_STRUCT_TYPE(attr, liq_attr)) return LIQ_INVALID_POINTER;
- if (!liq_image_has_rgba_pixels(img)) {
- return LIQ_UNSUPPORTED;
- }
-
- liq_histogram *hist = liq_histogram_create(attr);
- if (!hist) {
- return LIQ_OUT_OF_MEMORY;
- }
- liq_error err = liq_histogram_add_image(hist, attr, img);
- if (LIQ_OK != err) {
- return err;
- }
-
- err = liq_histogram_quantize_internal(hist, attr, false, result_output);
- liq_histogram_destroy(hist);
-
- return err;
-}
-
-LIQ_EXPORT LIQ_NONNULL liq_error liq_histogram_quantize(liq_histogram *input_hist, liq_attr *attr, liq_result **result_output) {
- return liq_histogram_quantize_internal(input_hist, attr, true, result_output);
-}
-
-LIQ_NONNULL static liq_error liq_histogram_quantize_internal(liq_histogram *input_hist, liq_attr *attr, bool fixed_result_colors, liq_result **result_output)
-{
- if (!CHECK_USER_POINTER(result_output)) return LIQ_INVALID_POINTER;
- *result_output = NULL;
-
- if (!CHECK_STRUCT_TYPE(attr, liq_attr)) return LIQ_INVALID_POINTER;
- if (!CHECK_STRUCT_TYPE(input_hist, liq_histogram)) return LIQ_INVALID_POINTER;
-
- if (liq_progress(attr, 0)) return LIQ_ABORTED;
-
- histogram *hist;
- liq_error err = finalize_histogram(input_hist, attr, &hist);
- if (err != LIQ_OK) {
- return err;
- }
-
- err = pngquant_quantize(hist, attr, input_hist->fixed_colors_count, input_hist->fixed_colors, input_hist->gamma, fixed_result_colors, result_output);
- pam_freeacolorhist(hist);
-
- return err;
-}
-
-LIQ_EXPORT LIQ_NONNULL liq_error liq_set_dithering_level(liq_result *res, float dither_level)
-{
- if (!CHECK_STRUCT_TYPE(res, liq_result)) return LIQ_INVALID_POINTER;
-
- if (res->remapping) {
- liq_remapping_result_destroy(res->remapping);
- res->remapping = NULL;
- }
-
- if (res->dither_level < 0 || res->dither_level > 1.0f) return LIQ_VALUE_OUT_OF_RANGE;
- res->dither_level = dither_level;
- return LIQ_OK;
-}
-
-LIQ_NONNULL static liq_remapping_result *liq_remapping_result_create(liq_result *result)
-{
- if (!CHECK_STRUCT_TYPE(result, liq_result)) {
- return NULL;
- }
-
- liq_remapping_result *res = result->malloc(sizeof(liq_remapping_result));
- if (!res) return NULL;
- *res = (liq_remapping_result) {
- .magic_header = liq_remapping_result_magic,
- .malloc = result->malloc,
- .free = result->free,
- .dither_level = result->dither_level,
- .use_dither_map = result->use_dither_map,
- .palette_error = result->palette_error,
- .gamma = result->gamma,
- .palette = pam_duplicate_colormap(result->palette),
- .progress_callback = result->progress_callback,
- .progress_callback_user_info = result->progress_callback_user_info,
- .progress_stage1 = result->use_dither_map ? 20 : 0,
- };
- return res;
-}
-
-LIQ_EXPORT LIQ_NONNULL double liq_get_output_gamma(const liq_result *result)
-{
- if (!CHECK_STRUCT_TYPE(result, liq_result)) return -1;
-
- return result->gamma;
-}
-
-LIQ_NONNULL static void liq_remapping_result_destroy(liq_remapping_result *result)
-{
- if (!CHECK_STRUCT_TYPE(result, liq_remapping_result)) return;
-
- if (result->palette) pam_freecolormap(result->palette);
- if (result->pixels) result->free(result->pixels);
-
- result->magic_header = liq_freed_magic;
- result->free(result);
-}
-
-LIQ_EXPORT LIQ_NONNULL void liq_result_destroy(liq_result *res)
-{
- if (!CHECK_STRUCT_TYPE(res, liq_result)) return;
-
- memset(&res->int_palette, 0, sizeof(liq_palette));
-
- if (res->remapping) {
- memset(&res->remapping->int_palette, 0, sizeof(liq_palette));
- liq_remapping_result_destroy(res->remapping);
- }
-
- pam_freecolormap(res->palette);
-
- res->magic_header = liq_freed_magic;
- res->free(res);
-}
-
-
-LIQ_EXPORT LIQ_NONNULL double liq_get_quantization_error(const liq_result *result) {
- if (!CHECK_STRUCT_TYPE(result, liq_result)) return -1;
-
- if (result->palette_error >= 0) {
- return mse_to_standard_mse(result->palette_error);
- }
-
- return -1;
-}
-
-LIQ_EXPORT LIQ_NONNULL double liq_get_remapping_error(const liq_result *result) {
- if (!CHECK_STRUCT_TYPE(result, liq_result)) return -1;
-
- if (result->remapping && result->remapping->palette_error >= 0) {
- return mse_to_standard_mse(result->remapping->palette_error);
- }
-
- return -1;
-}
-
-LIQ_EXPORT LIQ_NONNULL int liq_get_quantization_quality(const liq_result *result) {
- if (!CHECK_STRUCT_TYPE(result, liq_result)) return -1;
-
- if (result->palette_error >= 0) {
- return mse_to_quality(result->palette_error);
- }
-
- return -1;
-}
-
-LIQ_EXPORT LIQ_NONNULL int liq_get_remapping_quality(const liq_result *result) {
- if (!CHECK_STRUCT_TYPE(result, liq_result)) return -1;
-
- if (result->remapping && result->remapping->palette_error >= 0) {
- return mse_to_quality(result->remapping->palette_error);
- }
-
- return -1;
-}
-
-LIQ_NONNULL static int compare_popularity(const void *ch1, const void *ch2)
-{
- const float v1 = ((const colormap_item*)ch1)->popularity;
- const float v2 = ((const colormap_item*)ch2)->popularity;
- return v1 > v2 ? -1 : 1;
-}
-
-LIQ_NONNULL static void sort_palette_qsort(colormap *map, int start, int nelem)
-{
- if (!nelem) return;
- qsort(map->palette + start, nelem, sizeof(map->palette[0]), compare_popularity);
-}
-
-#define SWAP_PALETTE(map, a,b) { \
- const colormap_item tmp = (map)->palette[(a)]; \
- (map)->palette[(a)] = (map)->palette[(b)]; \
- (map)->palette[(b)] = tmp; }
-
-LIQ_NONNULL static void sort_palette(colormap *map, const liq_attr *options)
-{
- /*
- ** Step 3.5 [GRR]: remap the palette colors so that all entries with
- ** the maximal alpha value (i.e., fully opaque) are at the end and can
- ** therefore be omitted from the tRNS chunk.
- */
- if (options->last_index_transparent) {
- for(unsigned int i=0; i < map->colors; i++) {
- if (map->palette[i].acolor.a < 1.f/256.f) {
- const unsigned int old = i, transparent_dest = map->colors-1;
-
- SWAP_PALETTE(map, transparent_dest, old);
-
- /* colors sorted by popularity make pngs slightly more compressible */
- sort_palette_qsort(map, 0, map->colors-1);
- return;
- }
- }
- }
-
- unsigned int non_fixed_colors = 0;
- for(unsigned int i = 0; i < map->colors; i++) {
- if (map->palette[i].fixed) {
- break;
- }
- non_fixed_colors++;
- }
-
- /* move transparent colors to the beginning to shrink trns chunk */
- unsigned int num_transparent = 0;
- for(unsigned int i = 0; i < non_fixed_colors; i++) {
- if (map->palette[i].acolor.a < 255.f/256.f) {
- // current transparent color is swapped with earlier opaque one
- if (i != num_transparent) {
- SWAP_PALETTE(map, num_transparent, i);
- i--;
- }
- num_transparent++;
- }
- }
-
- liq_verbose_printf(options, " eliminated opaque tRNS-chunk entries...%d entr%s transparent", num_transparent, (num_transparent == 1)? "y" : "ies");
-
- /* colors sorted by popularity make pngs slightly more compressible
- * opaque and transparent are sorted separately
- */
- sort_palette_qsort(map, 0, num_transparent);
- sort_palette_qsort(map, num_transparent, non_fixed_colors - num_transparent);
-
- if (non_fixed_colors > 9 && map->colors > 16) {
- SWAP_PALETTE(map, 7, 1); // slightly improves compression
- SWAP_PALETTE(map, 8, 2);
- SWAP_PALETTE(map, 9, 3);
- }
-}
-
-inline static unsigned int posterize_channel(unsigned int color, unsigned int bits)
-{
- return (color & ~((1<> (8-bits));
-}
-
-LIQ_NONNULL static void set_rounded_palette(liq_palette *const dest, colormap *const map, const double gamma, unsigned int posterize)
-{
- float gamma_lut[256];
- to_f_set_gamma(gamma_lut, gamma);
-
- dest->count = map->colors;
- for(unsigned int x = 0; x < map->colors; ++x) {
- rgba_pixel px = f_to_rgb(gamma, map->palette[x].acolor);
-
- px.r = posterize_channel(px.r, posterize);
- px.g = posterize_channel(px.g, posterize);
- px.b = posterize_channel(px.b, posterize);
- px.a = posterize_channel(px.a, posterize);
-
- map->palette[x].acolor = rgba_to_f(gamma_lut, px); /* saves rounding error introduced by to_rgb, which makes remapping & dithering more accurate */
-
- if (!px.a && !map->palette[x].fixed) {
- px.r = 71; px.g = 112; px.b = 76;
- }
-
- dest->entries[x] = (liq_color){.r=px.r,.g=px.g,.b=px.b,.a=px.a};
- }
-}
-
-LIQ_EXPORT LIQ_NONNULL const liq_palette *liq_get_palette(liq_result *result)
-{
- if (!CHECK_STRUCT_TYPE(result, liq_result)) return NULL;
-
- if (result->remapping && result->remapping->int_palette.count) {
- return &result->remapping->int_palette;
- }
-
- if (!result->int_palette.count) {
- set_rounded_palette(&result->int_palette, result->palette, result->gamma, result->min_posterization_output);
- }
- return &result->int_palette;
-}
-
-LIQ_NONNULL static float remap_to_palette(liq_image *const input_image, unsigned char *const *const output_pixels, colormap *const map)
-{
- const int rows = input_image->height;
- const unsigned int cols = input_image->width;
- double remapping_error=0;
-
- if (!liq_image_get_row_f_init(input_image)) {
- return -1;
- }
- if (input_image->background && !liq_image_get_row_f_init(input_image->background)) {
- return -1;
- }
-
- const colormap_item *acolormap = map->palette;
-
- struct nearest_map *const n = nearest_init(map);
- const int transparent_index = input_image->background ? nearest_search(n, &(f_pixel){0,0,0,0}, 0, NULL) : 0;
-
-
- const unsigned int max_threads = omp_get_max_threads();
- LIQ_ARRAY(kmeans_state, average_color, (KMEANS_CACHE_LINE_GAP+map->colors) * max_threads);
- kmeans_init(map, max_threads, average_color);
-
- #pragma omp parallel for if (rows*cols > 3000) \
- schedule(static) default(none) shared(acolormap) shared(average_color) reduction(+:remapping_error)
- for(int row = 0; row < rows; ++row) {
- const f_pixel *const row_pixels = liq_image_get_row_f(input_image, row);
- const f_pixel *const bg_pixels = input_image->background && acolormap[transparent_index].acolor.a < 1.f/256.f ? liq_image_get_row_f(input_image->background, row) : NULL;
-
- unsigned int last_match=0;
- for(unsigned int col = 0; col < cols; ++col) {
- float diff;
- last_match = nearest_search(n, &row_pixels[col], last_match, &diff);
- if (bg_pixels && colordifference(bg_pixels[col], acolormap[last_match].acolor) <= diff) {
- last_match = transparent_index;
- }
- output_pixels[row][col] = last_match;
-
- remapping_error += diff;
- kmeans_update_color(row_pixels[col], 1.0, map, last_match, omp_get_thread_num(), average_color);
- }
- }
-
- kmeans_finalize(map, max_threads, average_color);
-
- nearest_free(n);
-
- return remapping_error / (input_image->width * input_image->height);
-}
-
-inline static f_pixel get_dithered_pixel(const float dither_level, const float max_dither_error, const f_pixel thiserr, const f_pixel px)
-{
- /* Use Floyd-Steinberg errors to adjust actual color. */
- const float sr = thiserr.r * dither_level,
- sg = thiserr.g * dither_level,
- sb = thiserr.b * dither_level,
- sa = thiserr.a * dither_level;
-
- float ratio = 1.0;
- const float max_overflow = 1.1f;
- const float max_underflow = -0.1f;
-
- // allowing some overflow prevents undithered bands caused by clamping of all channels
- if (px.r + sr > max_overflow) ratio = MIN(ratio, (max_overflow -px.r)/sr);
- else { if (px.r + sr < max_underflow) ratio = MIN(ratio, (max_underflow-px.r)/sr); }
- if (px.g + sg > max_overflow) ratio = MIN(ratio, (max_overflow -px.g)/sg);
- else { if (px.g + sg < max_underflow) ratio = MIN(ratio, (max_underflow-px.g)/sg); }
- if (px.b + sb > max_overflow) ratio = MIN(ratio, (max_overflow -px.b)/sb);
- else { if (px.b + sb < max_underflow) ratio = MIN(ratio, (max_underflow-px.b)/sb); }
-
- float a = px.a + sa;
- if (a > 1.f) { a = 1.f; }
- else if (a < 0) { a = 0; }
-
- // If dithering error is crazy high, don't propagate it that much
- // This prevents crazy geen pixels popping out of the blue (or red or black! ;)
- const float dither_error = sr*sr + sg*sg + sb*sb + sa*sa;
- if (dither_error > max_dither_error) {
- ratio *= 0.8f;
- } else if (dither_error < 2.f/256.f/256.f) {
- // don't dither areas that don't have noticeable error — makes file smaller
- return px;
- }
-
- return (f_pixel) {
- .r=px.r + sr * ratio,
- .g=px.g + sg * ratio,
- .b=px.b + sb * ratio,
- .a=a,
- };
-}
-
-/**
- Uses edge/noise map to apply dithering only to flat areas. Dithering on edges creates jagged lines, and noisy areas are "naturally" dithered.
-
- If output_image_is_remapped is true, only pixels noticeably changed by error diffusion will be written to output image.
- */
-LIQ_NONNULL static bool remap_to_palette_floyd(liq_image *input_image, unsigned char *const output_pixels[], liq_remapping_result *quant, const float max_dither_error, const bool output_image_is_remapped)
-{
- const int rows = input_image->height, cols = input_image->width;
- const unsigned char *dither_map = quant->use_dither_map ? (input_image->dither_map ? input_image->dither_map : input_image->edges) : NULL;
-
- const colormap *map = quant->palette;
- const colormap_item *acolormap = map->palette;
-
- if (!liq_image_get_row_f_init(input_image)) {
- return false;
- }
- if (input_image->background && !liq_image_get_row_f_init(input_image->background)) {
- return false;
- }
-
- /* Initialize Floyd-Steinberg error vectors. */
- const size_t errwidth = cols+2;
- f_pixel *restrict thiserr = input_image->malloc(errwidth * sizeof(thiserr[0]) * 2); // +2 saves from checking out of bounds access
- if (!thiserr) return false;
- f_pixel *restrict nexterr = thiserr + errwidth;
- memset(thiserr, 0, errwidth * sizeof(thiserr[0]));
-
- bool ok = true;
- struct nearest_map *const n = nearest_init(map);
- const int transparent_index = input_image->background ? nearest_search(n, &(f_pixel){0,0,0,0}, 0, NULL) : 0;
-
- // response to this value is non-linear and without it any value < 0.8 would give almost no dithering
- float base_dithering_level = quant->dither_level;
- base_dithering_level = 1.f - (1.f-base_dithering_level)*(1.f-base_dithering_level);
-
- if (dither_map) {
- base_dithering_level *= 1.f/255.f; // convert byte to float
- }
- base_dithering_level *= 15.f/16.f; // prevent small errors from accumulating
-
- int fs_direction = 1;
- unsigned int last_match=0;
- for (int row = 0; row < rows; ++row) {
- if (liq_remap_progress(quant, quant->progress_stage1 + row * (100.f - quant->progress_stage1) / rows)) {
- ok = false;
- break;
- }
-
- memset(nexterr, 0, errwidth * sizeof(nexterr[0]));
-
- int col = (fs_direction > 0) ? 0 : (cols - 1);
- const f_pixel *const row_pixels = liq_image_get_row_f(input_image, row);
- const f_pixel *const bg_pixels = input_image->background && acolormap[transparent_index].acolor.a < 1.f/256.f ? liq_image_get_row_f(input_image->background, row) : NULL;
-
- do {
- float dither_level = base_dithering_level;
- if (dither_map) {
- dither_level *= dither_map[row*cols + col];
- }
-
- const f_pixel spx = get_dithered_pixel(dither_level, max_dither_error, thiserr[col + 1], row_pixels[col]);
-
- const unsigned int guessed_match = output_image_is_remapped ? output_pixels[row][col] : last_match;
- float diff;
- last_match = nearest_search(n, &spx, guessed_match, &diff);
- f_pixel output_px = acolormap[last_match].acolor;
- if (bg_pixels && colordifference(bg_pixels[col], output_px) <= diff) {
- output_px = bg_pixels[col];
- output_pixels[row][col] = transparent_index;
- } else {
- output_pixels[row][col] = last_match;
- }
-
- f_pixel err = {
- .r = (spx.r - output_px.r),
- .g = (spx.g - output_px.g),
- .b = (spx.b - output_px.b),
- .a = (spx.a - output_px.a),
- };
-
- // If dithering error is crazy high, don't propagate it that much
- // This prevents crazy geen pixels popping out of the blue (or red or black! ;)
- if (err.r*err.r + err.g*err.g + err.b*err.b + err.a*err.a > max_dither_error) {
- err.r *= 0.75f;
- err.g *= 0.75f;
- err.b *= 0.75f;
- err.a *= 0.75f;
- }
-
- /* Propagate Floyd-Steinberg error terms. */
- if (fs_direction > 0) {
- thiserr[col + 2].a += err.a * (7.f/16.f);
- thiserr[col + 2].r += err.r * (7.f/16.f);
- thiserr[col + 2].g += err.g * (7.f/16.f);
- thiserr[col + 2].b += err.b * (7.f/16.f);
-
- nexterr[col + 2].a = err.a * (1.f/16.f);
- nexterr[col + 2].r = err.r * (1.f/16.f);
- nexterr[col + 2].g = err.g * (1.f/16.f);
- nexterr[col + 2].b = err.b * (1.f/16.f);
-
- nexterr[col + 1].a += err.a * (5.f/16.f);
- nexterr[col + 1].r += err.r * (5.f/16.f);
- nexterr[col + 1].g += err.g * (5.f/16.f);
- nexterr[col + 1].b += err.b * (5.f/16.f);
-
- nexterr[col ].a += err.a * (3.f/16.f);
- nexterr[col ].r += err.r * (3.f/16.f);
- nexterr[col ].g += err.g * (3.f/16.f);
- nexterr[col ].b += err.b * (3.f/16.f);
-
- } else {
- thiserr[col ].a += err.a * (7.f/16.f);
- thiserr[col ].r += err.r * (7.f/16.f);
- thiserr[col ].g += err.g * (7.f/16.f);
- thiserr[col ].b += err.b * (7.f/16.f);
-
- nexterr[col ].a = err.a * (1.f/16.f);
- nexterr[col ].r = err.r * (1.f/16.f);
- nexterr[col ].g = err.g * (1.f/16.f);
- nexterr[col ].b = err.b * (1.f/16.f);
-
- nexterr[col + 1].a += err.a * (5.f/16.f);
- nexterr[col + 1].r += err.r * (5.f/16.f);
- nexterr[col + 1].g += err.g * (5.f/16.f);
- nexterr[col + 1].b += err.b * (5.f/16.f);
-
- nexterr[col + 2].a += err.a * (3.f/16.f);
- nexterr[col + 2].r += err.r * (3.f/16.f);
- nexterr[col + 2].g += err.g * (3.f/16.f);
- nexterr[col + 2].b += err.b * (3.f/16.f);
- }
-
- // remapping is done in zig-zag
- col += fs_direction;
- if (fs_direction > 0) {
- if (col >= cols) break;
- } else {
- if (col < 0) break;
- }
- } while(1);
-
- f_pixel *const temperr = thiserr;
- thiserr = nexterr;
- nexterr = temperr;
- fs_direction = -fs_direction;
- }
-
- input_image->free(MIN(thiserr, nexterr)); // MIN because pointers were swapped
- nearest_free(n);
-
- return ok;
-}
-
-/* fixed colors are always included in the palette, so it would be wasteful to duplicate them in palette from histogram */
-LIQ_NONNULL static void remove_fixed_colors_from_histogram(histogram *hist, const int fixed_colors_count, const f_pixel fixed_colors[], const float target_mse)
-{
- const float max_difference = MAX(target_mse/2.f, 2.f/256.f/256.f);
- if (fixed_colors_count) {
- for(int j=0; j < hist->size; j++) {
- for(unsigned int i=0; i < fixed_colors_count; i++) {
- if (colordifference(hist->achv[j].acolor, fixed_colors[i]) < max_difference) {
- hist->achv[j] = hist->achv[--hist->size]; // remove color from histogram by overwriting with the last entry
- j--; break; // continue searching histogram
- }
- }
- }
- }
-}
-
-LIQ_EXPORT LIQ_NONNULL liq_error liq_histogram_add_colors(liq_histogram *input_hist, const liq_attr *options, const liq_histogram_entry entries[], int num_entries, double gamma)
-{
- if (!CHECK_STRUCT_TYPE(options, liq_attr)) return LIQ_INVALID_POINTER;
- if (!CHECK_STRUCT_TYPE(input_hist, liq_histogram)) return LIQ_INVALID_POINTER;
- if (!CHECK_USER_POINTER(entries)) return LIQ_INVALID_POINTER;
- if (gamma < 0 || gamma >= 1.0) return LIQ_VALUE_OUT_OF_RANGE;
- if (num_entries <= 0 || num_entries > 1<<30) return LIQ_VALUE_OUT_OF_RANGE;
-
- if (input_hist->ignorebits > 0 && input_hist->had_image_added) {
- return LIQ_UNSUPPORTED;
- }
- input_hist->ignorebits = 0;
-
- input_hist->had_image_added = true;
- input_hist->gamma = gamma ? gamma : 0.45455;
-
- if (!input_hist->acht) {
- input_hist->acht = pam_allocacolorhash(~0, num_entries*num_entries, 0, options->malloc, options->free);
- if (!input_hist->acht) {
- return LIQ_OUT_OF_MEMORY;
- }
- }
- // Fake image size. It's only for hash size estimates.
- if (!input_hist->acht->cols) {
- input_hist->acht->cols = num_entries;
- }
- input_hist->acht->rows += num_entries;
-
- const unsigned int hash_size = input_hist->acht->hash_size;
- for(int i=0; i < num_entries; i++) {
- const rgba_pixel rgba = {
- .r = entries[i].color.r,
- .g = entries[i].color.g,
- .b = entries[i].color.b,
- .a = entries[i].color.a,
- };
- union rgba_as_int px = {rgba};
- unsigned int hash;
- if (px.rgba.a) {
- hash = px.l % hash_size;
- } else {
- hash=0; px.l=0;
- }
- if (!pam_add_to_hash(input_hist->acht, hash, entries[i].count, px, i, num_entries)) {
- return LIQ_OUT_OF_MEMORY;
- }
- }
-
- return LIQ_OK;
-}
-
-LIQ_EXPORT LIQ_NONNULL liq_error liq_histogram_add_image(liq_histogram *input_hist, const liq_attr *options, liq_image *input_image)
-{
- if (!CHECK_STRUCT_TYPE(options, liq_attr)) return LIQ_INVALID_POINTER;
- if (!CHECK_STRUCT_TYPE(input_hist, liq_histogram)) return LIQ_INVALID_POINTER;
- if (!CHECK_STRUCT_TYPE(input_image, liq_image)) return LIQ_INVALID_POINTER;
-
- const unsigned int cols = input_image->width, rows = input_image->height;
-
- if (!input_image->importance_map && options->use_contrast_maps) {
- contrast_maps(input_image);
- }
-
- input_hist->gamma = input_image->gamma;
-
- for(int i = 0; i < input_image->fixed_colors_count; i++) {
- liq_error res = liq_histogram_add_fixed_color_f(input_hist, input_image->fixed_colors[i]);
- if (res != LIQ_OK) {
- return res;
- }
- }
-
- /*
- ** Step 2: attempt to make a histogram of the colors, unclustered.
- ** If at first we don't succeed, increase ignorebits to increase color
- ** coherence and try again.
- */
-
- if (liq_progress(options, options->progress_stage1 * 0.4f)) {
- return LIQ_ABORTED;
- }
-
- const bool all_rows_at_once = liq_image_can_use_rgba_rows(input_image);
-
- // Usual solution is to start from scratch when limit is exceeded, but that's not possible if it's not
- // the first image added
- const unsigned int max_histogram_entries = input_hist->had_image_added ? ~0 : options->max_histogram_entries;
- do {
- if (!input_hist->acht) {
- input_hist->acht = pam_allocacolorhash(max_histogram_entries, rows*cols, input_hist->ignorebits, options->malloc, options->free);
- }
- if (!input_hist->acht) return LIQ_OUT_OF_MEMORY;
-
- // histogram uses noise contrast map for importance. Color accuracy in noisy areas is not very important.
- // noise map does not include edges to avoid ruining anti-aliasing
- for(unsigned int row=0; row < rows; row++) {
- bool added_ok;
- if (all_rows_at_once) {
- added_ok = pam_computeacolorhash(input_hist->acht, (const rgba_pixel *const *)input_image->rows, cols, rows, input_image->importance_map);
- if (added_ok) break;
- } else {
- const rgba_pixel* rows_p[1] = { liq_image_get_row_rgba(input_image, row) };
- added_ok = pam_computeacolorhash(input_hist->acht, rows_p, cols, 1, input_image->importance_map ? &input_image->importance_map[row * cols] : NULL);
- }
- if (!added_ok) {
- input_hist->ignorebits++;
- liq_verbose_printf(options, " too many colors! Scaling colors to improve clustering... %d", input_hist->ignorebits);
- pam_freeacolorhash(input_hist->acht);
- input_hist->acht = NULL;
- if (liq_progress(options, options->progress_stage1 * 0.6f)) return LIQ_ABORTED;
- break;
- }
- }
- } while(!input_hist->acht);
-
- input_hist->had_image_added = true;
-
- liq_image_free_importance_map(input_image);
-
- if (input_image->free_pixels && input_image->f_pixels) {
- liq_image_free_rgba_source(input_image); // bow can free the RGBA source if copy has been made in f_pixels
- }
-
- return LIQ_OK;
-}
-
-LIQ_NONNULL static liq_error finalize_histogram(liq_histogram *input_hist, liq_attr *options, histogram **hist_output)
-{
- if (liq_progress(options, options->progress_stage1 * 0.9f)) {
- return LIQ_ABORTED;
- }
-
- if (!input_hist->acht) {
- return LIQ_BITMAP_NOT_AVAILABLE;
- }
-
- histogram *hist = pam_acolorhashtoacolorhist(input_hist->acht, input_hist->gamma, options->malloc, options->free);
- pam_freeacolorhash(input_hist->acht);
- input_hist->acht = NULL;
-
- if (!hist) {
- return LIQ_OUT_OF_MEMORY;
- }
- liq_verbose_printf(options, " made histogram...%d colors found", hist->size);
- remove_fixed_colors_from_histogram(hist, input_hist->fixed_colors_count, input_hist->fixed_colors, options->target_mse);
-
- *hist_output = hist;
- return LIQ_OK;
-}
-
-LIQ_NONNULL static void modify_alpha(liq_image *input_image, rgba_pixel *const row_pixels)
-{
- /* IE6 makes colors with even slightest transparency completely transparent,
- thus to improve situation in IE, make colors that are less than ~10% transparent
- completely opaque */
-
- const float min_opaque_val = input_image->min_opaque_val;
- const float almost_opaque_val = min_opaque_val * 169.f/256.f;
- const unsigned int almost_opaque_val_int = (min_opaque_val * 169.f/256.f)*255.f;
-
- for(unsigned int col = 0; col < input_image->width; col++) {
- const rgba_pixel px = row_pixels[col];
-
- /* ie bug: to avoid visible step caused by forced opaqueness, linearily raise opaqueness of almost-opaque colors */
- if (px.a >= almost_opaque_val_int) {
- float al = px.a / 255.f;
- al = almost_opaque_val + (al-almost_opaque_val) * (1.f-almost_opaque_val) / (min_opaque_val-almost_opaque_val);
- al *= 256.f;
- row_pixels[col].a = al >= 255.f ? 255 : al;
- }
- }
-}
-
-/**
- Builds two maps:
- importance_map - approximation of areas with high-frequency noise, except straight edges. 1=flat, 0=noisy.
- edges - noise map including all edges
- */
-LIQ_NONNULL static void contrast_maps(liq_image *image)
-{
- const unsigned int cols = image->width, rows = image->height;
- if (cols < 4 || rows < 4 || (3*cols*rows) > LIQ_HIGH_MEMORY_LIMIT) {
- return;
- }
-
- unsigned char *restrict noise = image->importance_map ? image->importance_map : image->malloc(cols*rows);
- image->importance_map = NULL;
- unsigned char *restrict edges = image->edges ? image->edges : image->malloc(cols*rows);
- image->edges = NULL;
-
- unsigned char *restrict tmp = image->malloc(cols*rows);
-
- if (!noise || !edges || !tmp || !liq_image_get_row_f_init(image)) {
- image->free(noise);
- image->free(edges);
- image->free(tmp);
- return;
- }
-
- const f_pixel *curr_row, *prev_row, *next_row;
- curr_row = prev_row = next_row = liq_image_get_row_f(image, 0);
-
- for (unsigned int j=0; j < rows; j++) {
- prev_row = curr_row;
- curr_row = next_row;
- next_row = liq_image_get_row_f(image, MIN(rows-1,j+1));
-
- f_pixel prev, curr = curr_row[0], next=curr;
- for (unsigned int i=0; i < cols; i++) {
- prev=curr;
- curr=next;
- next = curr_row[MIN(cols-1,i+1)];
-
- // contrast is difference between pixels neighbouring horizontally and vertically
- const float a = fabsf(prev.a+next.a - curr.a*2.f),
- r = fabsf(prev.r+next.r - curr.r*2.f),
- g = fabsf(prev.g+next.g - curr.g*2.f),
- b = fabsf(prev.b+next.b - curr.b*2.f);
-
- const f_pixel prevl = prev_row[i];
- const f_pixel nextl = next_row[i];
-
- const float a1 = fabsf(prevl.a+nextl.a - curr.a*2.f),
- r1 = fabsf(prevl.r+nextl.r - curr.r*2.f),
- g1 = fabsf(prevl.g+nextl.g - curr.g*2.f),
- b1 = fabsf(prevl.b+nextl.b - curr.b*2.f);
-
- const float horiz = MAX(MAX(a,r),MAX(g,b));
- const float vert = MAX(MAX(a1,r1),MAX(g1,b1));
- const float edge = MAX(horiz,vert);
- float z = edge - fabsf(horiz-vert)*.5f;
- z = 1.f - MAX(z,MIN(horiz,vert));
- z *= z; // noise is amplified
- z *= z;
- // 85 is about 1/3rd of weight (not 0, because noisy pixels still need to be included, just not as precisely).
- const unsigned int z_int = 85 + (unsigned int)(z * 171.f);
- noise[j*cols+i] = MIN(z_int, 255);
- const int e_int = 255 - (int)(edge * 256.f);
- edges[j*cols+i] = e_int > 0 ? MIN(e_int, 255) : 0;
- }
- }
-
- // noise areas are shrunk and then expanded to remove thin edges from the map
- liq_max3(noise, tmp, cols, rows);
- liq_max3(tmp, noise, cols, rows);
-
- liq_blur(noise, tmp, noise, cols, rows, 3);
-
- liq_max3(noise, tmp, cols, rows);
-
- liq_min3(tmp, noise, cols, rows);
- liq_min3(noise, tmp, cols, rows);
- liq_min3(tmp, noise, cols, rows);
-
- liq_min3(edges, tmp, cols, rows);
- liq_max3(tmp, edges, cols, rows);
- for(unsigned int i=0; i < cols*rows; i++) edges[i] = MIN(noise[i], edges[i]);
-
- image->free(tmp);
-
- image->importance_map = noise;
- image->edges = edges;
-}
-
-/**
- * Builds map of neighbor pixels mapped to the same palette entry
- *
- * For efficiency/simplicity it mainly looks for same consecutive pixels horizontally
- * and peeks 1 pixel above/below. Full 2d algorithm doesn't improve it significantly.
- * Correct flood fill doesn't have visually good properties.
- */
-LIQ_NONNULL static void update_dither_map(liq_image *input_image, unsigned char *const *const row_pointers, colormap *map)
-{
- const unsigned int width = input_image->width;
- const unsigned int height = input_image->height;
- unsigned char *const edges = input_image->edges;
-
- for(unsigned int row=0; row < height; row++) {
- unsigned char lastpixel = row_pointers[row][0];
- unsigned int lastcol=0;
-
- for(unsigned int col=1; col < width; col++) {
- const unsigned char px = row_pointers[row][col];
- if (input_image->background && map->palette[px].acolor.a < 1.f/256.f) {
- // Transparency may or may not create an edge. When there's an explicit background set, assume no edge.
- continue;
- }
-
- if (px != lastpixel || col == width-1) {
- int neighbor_count = 10 * (col-lastcol);
-
- unsigned int i=lastcol;
- while(i < col) {
- if (row > 0) {
- unsigned char pixelabove = row_pointers[row-1][i];
- if (pixelabove == lastpixel) neighbor_count += 15;
- }
- if (row < height-1) {
- unsigned char pixelbelow = row_pointers[row+1][i];
- if (pixelbelow == lastpixel) neighbor_count += 15;
- }
- i++;
- }
-
- while(lastcol <= col) {
- int e = edges[row*width + lastcol];
- edges[row*width + lastcol++] = (e+128) * (255.f/(255+128)) * (1.f - 20.f / (20 + neighbor_count));
- }
- lastpixel = px;
- }
- }
- }
- input_image->dither_map = input_image->edges;
- input_image->edges = NULL;
-}
-
-/**
- * Palette can be NULL, in which case it creates a new palette from scratch.
- */
-static colormap *add_fixed_colors_to_palette(colormap *palette, const int max_colors, const f_pixel fixed_colors[], const int fixed_colors_count, void* (*malloc)(size_t), void (*free)(void*))
-{
- if (!fixed_colors_count) return palette;
-
- colormap *newpal = pam_colormap(MIN(max_colors, (palette ? palette->colors : 0) + fixed_colors_count), malloc, free);
- unsigned int i=0;
- if (palette && fixed_colors_count < max_colors) {
- unsigned int palette_max = MIN(palette->colors, max_colors - fixed_colors_count);
- for(; i < palette_max; i++) {
- newpal->palette[i] = palette->palette[i];
- }
- }
- for(int j=0; j < MIN(max_colors, fixed_colors_count); j++) {
- newpal->palette[i++] = (colormap_item){
- .acolor = fixed_colors[j],
- .fixed = true,
- };
- }
- if (palette) pam_freecolormap(palette);
- return newpal;
-}
-
-LIQ_NONNULL static void adjust_histogram_callback(hist_item *item, float diff)
-{
- item->adjusted_weight = (item->perceptual_weight+item->adjusted_weight) * (sqrtf(1.f+diff));
-}
-
-/**
- Repeats mediancut with different histogram weights to find palette with minimum error.
-
- feedback_loop_trials controls how long the search will take. < 0 skips the iteration.
- */
-static colormap *find_best_palette(histogram *hist, const liq_attr *options, const double max_mse, const f_pixel fixed_colors[], const unsigned int fixed_colors_count, double *palette_error_p)
-{
- unsigned int max_colors = options->max_colors;
-
- // if output is posterized it doesn't make sense to aim for perfrect colors, so increase target_mse
- // at this point actual gamma is not set, so very conservative posterization estimate is used
- const double target_mse = MIN(max_mse, MAX(options->target_mse, pow((1<min_posterization_output)/1024.0, 2)));
- int feedback_loop_trials = options->feedback_loop_trials;
- if (hist->size > 5000) {feedback_loop_trials = (feedback_loop_trials*3 + 3)/4;}
- if (hist->size > 25000) {feedback_loop_trials = (feedback_loop_trials*3 + 3)/4;}
- if (hist->size > 50000) {feedback_loop_trials = (feedback_loop_trials*3 + 3)/4;}
- if (hist->size > 100000) {feedback_loop_trials = (feedback_loop_trials*3 + 3)/4;}
- colormap *acolormap = NULL;
- double least_error = MAX_DIFF;
- double target_mse_overshoot = feedback_loop_trials>0 ? 1.05 : 1.0;
- const float total_trials = (float)(feedback_loop_trials>0?feedback_loop_trials:1);
-
- do {
- colormap *newmap;
- if (hist->size && fixed_colors_count < max_colors) {
- newmap = mediancut(hist, max_colors-fixed_colors_count, target_mse * target_mse_overshoot, MAX(MAX(45.0/65536.0, target_mse), least_error)*1.2,
- options->malloc, options->free);
- } else {
- feedback_loop_trials = 0;
- newmap = NULL;
- }
- newmap = add_fixed_colors_to_palette(newmap, max_colors, fixed_colors, fixed_colors_count, options->malloc, options->free);
- if (!newmap) {
- return NULL;
- }
-
- if (feedback_loop_trials <= 0) {
- return newmap;
- }
-
- // after palette has been created, total error (MSE) is calculated to keep the best palette
- // at the same time K-Means iteration is done to improve the palette
- // and histogram weights are adjusted based on remapping error to give more weight to poorly matched colors
-
- const bool first_run_of_target_mse = !acolormap && target_mse > 0;
- double total_error = kmeans_do_iteration(hist, newmap, first_run_of_target_mse ? NULL : adjust_histogram_callback);
-
- // goal is to increase quality or to reduce number of colors used if quality is good enough
- if (!acolormap || total_error < least_error || (total_error <= target_mse && newmap->colors < max_colors)) {
- if (acolormap) pam_freecolormap(acolormap);
- acolormap = newmap;
-
- if (total_error < target_mse && total_error > 0) {
- // K-Means iteration improves quality above what mediancut aims for
- // this compensates for it, making mediancut aim for worse
- target_mse_overshoot = MIN(target_mse_overshoot*1.25, target_mse/total_error);
- }
-
- least_error = total_error;
-
- // if number of colors could be reduced, try to keep it that way
- // but allow extra color as a bit of wiggle room in case quality can be improved too
- max_colors = MIN(newmap->colors+1, max_colors);
-
- feedback_loop_trials -= 1; // asymptotic improvement could make it go on forever
- } else {
- for(unsigned int j=0; j < hist->size; j++) {
- hist->achv[j].adjusted_weight = (hist->achv[j].perceptual_weight + hist->achv[j].adjusted_weight)/2.0;
- }
-
- target_mse_overshoot = 1.0;
- feedback_loop_trials -= 6;
- // if error is really bad, it's unlikely to improve, so end sooner
- if (total_error > least_error*4) feedback_loop_trials -= 3;
- pam_freecolormap(newmap);
- }
-
- float fraction_done = 1.f-MAX(0.f, feedback_loop_trials/total_trials);
- if (liq_progress(options, options->progress_stage1 + fraction_done * options->progress_stage2)) break;
- liq_verbose_printf(options, " selecting colors...%d%%", (int)(100.f * fraction_done));
- }
- while(feedback_loop_trials > 0);
-
- *palette_error_p = least_error;
- return acolormap;
-}
-
-static colormap *histogram_to_palette(const histogram *hist, const liq_attr *options) {
- if (!hist->size) {
- return NULL;
- }
- colormap *acolormap = pam_colormap(hist->size, options->malloc, options->free);
- for(unsigned int i=0; i < hist->size; i++) {
- acolormap->palette[i].acolor = hist->achv[i].acolor;
- acolormap->palette[i].popularity = hist->achv[i].perceptual_weight;
- }
- return acolormap;
-}
-
-LIQ_NONNULL static liq_error pngquant_quantize(histogram *hist, const liq_attr *options, const int fixed_colors_count, const f_pixel fixed_colors[], const double gamma, bool fixed_result_colors, liq_result **result_output)
-{
- colormap *acolormap;
- double palette_error = -1;
-
- assert((verbose_print(options, "SLOW debug checks enabled. Recompile with NDEBUG for normal operation."),1));
-
- const bool few_input_colors = hist->size+fixed_colors_count <= options->max_colors;
-
- if (liq_progress(options, options->progress_stage1)) return LIQ_ABORTED;
-
- // If image has few colors to begin with (and no quality degradation is required)
- // then it's possible to skip quantization entirely
- if (few_input_colors && options->target_mse == 0) {
- acolormap = add_fixed_colors_to_palette(histogram_to_palette(hist, options), options->max_colors, fixed_colors, fixed_colors_count, options->malloc, options->free);
- palette_error = 0;
- } else {
- const double max_mse = options->max_mse * (few_input_colors ? 0.33 : 1.0); // when degrading image that's already paletted, require much higher improvement, since pal2pal often looks bad and there's little gain
- acolormap = find_best_palette(hist, options, max_mse, fixed_colors, fixed_colors_count, &palette_error);
- if (!acolormap) {
- return LIQ_VALUE_OUT_OF_RANGE;
- }
-
- // K-Means iteration approaches local minimum for the palette
- double iteration_limit = options->kmeans_iteration_limit;
- unsigned int iterations = options->kmeans_iterations;
-
- if (!iterations && palette_error < 0 && max_mse < MAX_DIFF) iterations = 1; // otherwise total error is never calculated and MSE limit won't work
-
- if (iterations) {
- // likely_colormap_index (used and set in kmeans_do_iteration) can't point to index outside colormap
- if (acolormap->colors < 256) for(unsigned int j=0; j < hist->size; j++) {
- if (hist->achv[j].tmp.likely_colormap_index >= acolormap->colors) {
- hist->achv[j].tmp.likely_colormap_index = 0; // actual value doesn't matter, as the guess is out of date anyway
- }
- }
-
- if (hist->size > 5000) {iterations = (iterations*3 + 3)/4;}
- if (hist->size > 25000) {iterations = (iterations*3 + 3)/4;}
- if (hist->size > 50000) {iterations = (iterations*3 + 3)/4;}
- if (hist->size > 100000) {iterations = (iterations*3 + 3)/4; iteration_limit *= 2;}
-
- verbose_print(options, " moving colormap towards local minimum");
-
- double previous_palette_error = MAX_DIFF;
-
- for(unsigned int i=0; i < iterations; i++) {
- palette_error = kmeans_do_iteration(hist, acolormap, NULL);
-
- if (liq_progress(options, options->progress_stage1 + options->progress_stage2 + (i * options->progress_stage3 * 0.9f) / iterations)) {
- break;
- }
-
- if (fabs(previous_palette_error-palette_error) < iteration_limit) {
- break;
- }
-
- if (palette_error > max_mse*1.5) { // probably hopeless
- if (palette_error > max_mse*3.0) break; // definitely hopeless
- i++;
- }
-
- previous_palette_error = palette_error;
- }
- }
-
- if (palette_error > max_mse) {
- liq_verbose_printf(options, " image degradation MSE=%.3f (Q=%d) exceeded limit of %.3f (%d)",
- mse_to_standard_mse(palette_error), mse_to_quality(palette_error),
- mse_to_standard_mse(max_mse), mse_to_quality(max_mse));
- pam_freecolormap(acolormap);
- return LIQ_QUALITY_TOO_LOW;
- }
- }
-
- if (liq_progress(options, options->progress_stage1 + options->progress_stage2 + options->progress_stage3 * 0.95f)) {
- pam_freecolormap(acolormap);
- return LIQ_ABORTED;
- }
-
- sort_palette(acolormap, options);
-
- // If palette was created from a multi-image histogram,
- // then it shouldn't be optimized for one image during remapping
- if (fixed_result_colors) {
- for(unsigned int i=0; i < acolormap->colors; i++) {
- acolormap->palette[i].fixed = true;
- }
- }
-
- liq_result *result = options->malloc(sizeof(liq_result));
- if (!result) return LIQ_OUT_OF_MEMORY;
- *result = (liq_result){
- .magic_header = liq_result_magic,
- .malloc = options->malloc,
- .free = options->free,
- .palette = acolormap,
- .palette_error = palette_error,
- .use_dither_map = options->use_dither_map,
- .gamma = gamma,
- .min_posterization_output = options->min_posterization_output,
- };
- *result_output = result;
- return LIQ_OK;
-}
-
-LIQ_EXPORT LIQ_NONNULL liq_error liq_write_remapped_image(liq_result *result, liq_image *input_image, void *buffer, size_t buffer_size)
-{
- if (!CHECK_STRUCT_TYPE(result, liq_result)) {
- return LIQ_INVALID_POINTER;
- }
- if (!CHECK_STRUCT_TYPE(input_image, liq_image)) {
- return LIQ_INVALID_POINTER;
- }
- if (!CHECK_USER_POINTER(buffer)) {
- return LIQ_INVALID_POINTER;
- }
-
- const size_t required_size = input_image->width * input_image->height;
- if (buffer_size < required_size) {
- return LIQ_BUFFER_TOO_SMALL;
- }
-
- LIQ_ARRAY(unsigned char *, rows, input_image->height);
- unsigned char *buffer_bytes = buffer;
- for(unsigned int i=0; i < input_image->height; i++) {
- rows[i] = &buffer_bytes[input_image->width * i];
- }
- return liq_write_remapped_image_rows(result, input_image, rows);
-}
-
-LIQ_EXPORT LIQ_NONNULL liq_error liq_write_remapped_image_rows(liq_result *quant, liq_image *input_image, unsigned char **row_pointers)
-{
- if (!CHECK_STRUCT_TYPE(quant, liq_result)) return LIQ_INVALID_POINTER;
- if (!CHECK_STRUCT_TYPE(input_image, liq_image)) return LIQ_INVALID_POINTER;
- for(unsigned int i=0; i < input_image->height; i++) {
- if (!CHECK_USER_POINTER(row_pointers+i) || !CHECK_USER_POINTER(row_pointers[i])) return LIQ_INVALID_POINTER;
- }
-
- if (quant->remapping) {
- liq_remapping_result_destroy(quant->remapping);
- }
- liq_remapping_result *const result = quant->remapping = liq_remapping_result_create(quant);
- if (!result) return LIQ_OUT_OF_MEMORY;
-
- if (!input_image->edges && !input_image->dither_map && quant->use_dither_map) {
- contrast_maps(input_image);
- }
-
- if (liq_remap_progress(result, result->progress_stage1 * 0.25f)) {
- return LIQ_ABORTED;
- }
-
- /*
- ** Step 4: map the colors in the image to their closest match in the
- ** new colormap, and write 'em out.
- */
-
- float remapping_error = result->palette_error;
- if (result->dither_level == 0) {
- set_rounded_palette(&result->int_palette, result->palette, result->gamma, quant->min_posterization_output);
- remapping_error = remap_to_palette(input_image, row_pointers, result->palette);
- } else {
- const bool is_image_huge = (input_image->width * input_image->height) > 2000 * 2000;
- const bool allow_dither_map = result->use_dither_map == 2 || (!is_image_huge && result->use_dither_map);
- const bool generate_dither_map = allow_dither_map && (input_image->edges && !input_image->dither_map);
- if (generate_dither_map) {
- // If dithering (with dither map) is required, this image is used to find areas that require dithering
- remapping_error = remap_to_palette(input_image, row_pointers, result->palette);
- update_dither_map(input_image, row_pointers, result->palette);
- }
-
- if (liq_remap_progress(result, result->progress_stage1 * 0.5f)) {
- return LIQ_ABORTED;
- }
-
- // remapping above was the last chance to do K-Means iteration, hence the final palette is set after remapping
- set_rounded_palette(&result->int_palette, result->palette, result->gamma, quant->min_posterization_output);
-
- if (!remap_to_palette_floyd(input_image, row_pointers, result, MAX(remapping_error*2.4, 16.f/256.f), generate_dither_map)) {
- return LIQ_ABORTED;
- }
- }
-
- // remapping error from dithered image is absurd, so always non-dithered value is used
- // palette_error includes some perceptual weighting from histogram which is closer correlated with dssim
- // so that should be used when possible.
- if (result->palette_error < 0) {
- result->palette_error = remapping_error;
- }
-
- return LIQ_OK;
-}
-
-LIQ_EXPORT int liq_version() {
- return LIQ_VERSION;
-}
diff --git a/vendor/code.ivysaur.me/imagequant/libimagequant.h b/vendor/code.ivysaur.me/imagequant/libimagequant.h
deleted file mode 100644
index c8f84b5..0000000
--- a/vendor/code.ivysaur.me/imagequant/libimagequant.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * https://pngquant.org
- */
-
-#ifndef LIBIMAGEQUANT_H
-#define LIBIMAGEQUANT_H
-
-#ifdef IMAGEQUANT_EXPORTS
-#define LIQ_EXPORT __declspec(dllexport)
-#endif
-
-#ifndef LIQ_EXPORT
-#define LIQ_EXPORT extern
-#endif
-
-#define LIQ_VERSION 21200
-#define LIQ_VERSION_STRING "2.12.2"
-
-#ifndef LIQ_PRIVATE
-#if defined(__GNUC__) || defined (__llvm__)
-#define LIQ_PRIVATE __attribute__((visibility("hidden")))
-#define LIQ_NONNULL __attribute__((nonnull))
-#define LIQ_USERESULT __attribute__((warn_unused_result))
-#else
-#define LIQ_PRIVATE
-#define LIQ_NONNULL
-#define LIQ_USERESULT
-#endif
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include
-
-typedef struct liq_attr liq_attr;
-typedef struct liq_image liq_image;
-typedef struct liq_result liq_result;
-typedef struct liq_histogram liq_histogram;
-
-typedef struct liq_color {
- unsigned char r, g, b, a;
-} liq_color;
-
-typedef struct liq_palette {
- unsigned int count;
- liq_color entries[256];
-} liq_palette;
-
-typedef enum liq_error {
- LIQ_OK = 0,
- LIQ_QUALITY_TOO_LOW = 99,
- LIQ_VALUE_OUT_OF_RANGE = 100,
- LIQ_OUT_OF_MEMORY,
- LIQ_ABORTED,
- LIQ_BITMAP_NOT_AVAILABLE,
- LIQ_BUFFER_TOO_SMALL,
- LIQ_INVALID_POINTER,
- LIQ_UNSUPPORTED,
-} liq_error;
-
-enum liq_ownership {
- LIQ_OWN_ROWS=4,
- LIQ_OWN_PIXELS=8,
- LIQ_COPY_PIXELS=16,
-};
-
-typedef struct liq_histogram_entry {
- liq_color color;
- unsigned int count;
-} liq_histogram_entry;
-
-LIQ_EXPORT LIQ_USERESULT liq_attr* liq_attr_create(void);
-LIQ_EXPORT LIQ_USERESULT liq_attr* liq_attr_create_with_allocator(void* (*malloc)(size_t), void (*free)(void*));
-LIQ_EXPORT LIQ_USERESULT liq_attr* liq_attr_copy(const liq_attr *orig) LIQ_NONNULL;
-LIQ_EXPORT void liq_attr_destroy(liq_attr *attr) LIQ_NONNULL;
-
-LIQ_EXPORT LIQ_USERESULT liq_histogram* liq_histogram_create(const liq_attr* attr);
-LIQ_EXPORT liq_error liq_histogram_add_image(liq_histogram *hist, const liq_attr *attr, liq_image* image) LIQ_NONNULL;
-LIQ_EXPORT liq_error liq_histogram_add_colors(liq_histogram *hist, const liq_attr *attr, const liq_histogram_entry entries[], int num_entries, double gamma) LIQ_NONNULL;
-LIQ_EXPORT liq_error liq_histogram_add_fixed_color(liq_histogram *hist, liq_color color, double gamma) LIQ_NONNULL;
-LIQ_EXPORT void liq_histogram_destroy(liq_histogram *hist) LIQ_NONNULL;
-
-LIQ_EXPORT liq_error liq_set_max_colors(liq_attr* attr, int colors) LIQ_NONNULL;
-LIQ_EXPORT LIQ_USERESULT int liq_get_max_colors(const liq_attr* attr) LIQ_NONNULL;
-LIQ_EXPORT liq_error liq_set_speed(liq_attr* attr, int speed) LIQ_NONNULL;
-LIQ_EXPORT LIQ_USERESULT int liq_get_speed(const liq_attr* attr) LIQ_NONNULL;
-LIQ_EXPORT liq_error liq_set_min_opacity(liq_attr* attr, int min) LIQ_NONNULL;
-LIQ_EXPORT LIQ_USERESULT int liq_get_min_opacity(const liq_attr* attr) LIQ_NONNULL;
-LIQ_EXPORT liq_error liq_set_min_posterization(liq_attr* attr, int bits) LIQ_NONNULL;
-LIQ_EXPORT LIQ_USERESULT int liq_get_min_posterization(const liq_attr* attr) LIQ_NONNULL;
-LIQ_EXPORT liq_error liq_set_quality(liq_attr* attr, int minimum, int maximum) LIQ_NONNULL;
-LIQ_EXPORT LIQ_USERESULT int liq_get_min_quality(const liq_attr* attr) LIQ_NONNULL;
-LIQ_EXPORT LIQ_USERESULT int liq_get_max_quality(const liq_attr* attr) LIQ_NONNULL;
-LIQ_EXPORT void liq_set_last_index_transparent(liq_attr* attr, int is_last) LIQ_NONNULL;
-
-typedef void liq_log_callback_function(const liq_attr*, const char *message, void* user_info);
-typedef void liq_log_flush_callback_function(const liq_attr*, void* user_info);
-LIQ_EXPORT void liq_set_log_callback(liq_attr*, liq_log_callback_function*, void* user_info);
-LIQ_EXPORT void liq_set_log_flush_callback(liq_attr*, liq_log_flush_callback_function*, void* user_info);
-
-typedef int liq_progress_callback_function(float progress_percent, void* user_info);
-LIQ_EXPORT void liq_attr_set_progress_callback(liq_attr*, liq_progress_callback_function*, void* user_info);
-LIQ_EXPORT void liq_result_set_progress_callback(liq_result*, liq_progress_callback_function*, void* user_info);
-
-// The rows and their data are not modified. The type of `rows` is non-const only due to a bug in C's typesystem design.
-LIQ_EXPORT LIQ_USERESULT liq_image *liq_image_create_rgba_rows(const liq_attr *attr, void *const rows[], int width, int height, double gamma) LIQ_NONNULL;
-LIQ_EXPORT LIQ_USERESULT liq_image *liq_image_create_rgba(const liq_attr *attr, const void *bitmap, int width, int height, double gamma) LIQ_NONNULL;
-
-typedef void liq_image_get_rgba_row_callback(liq_color row_out[], int row, int width, void* user_info);
-LIQ_EXPORT LIQ_USERESULT liq_image *liq_image_create_custom(const liq_attr *attr, liq_image_get_rgba_row_callback *row_callback, void* user_info, int width, int height, double gamma);
-
-LIQ_EXPORT liq_error liq_image_set_memory_ownership(liq_image *image, int ownership_flags) LIQ_NONNULL;
-LIQ_EXPORT liq_error liq_image_set_background(liq_image *img, liq_image *background_image) LIQ_NONNULL;
-LIQ_EXPORT liq_error liq_image_set_importance_map(liq_image *img, unsigned char buffer[], size_t buffer_size, enum liq_ownership memory_handling) LIQ_NONNULL;
-LIQ_EXPORT liq_error liq_image_add_fixed_color(liq_image *img, liq_color color) LIQ_NONNULL;
-LIQ_EXPORT LIQ_USERESULT int liq_image_get_width(const liq_image *img) LIQ_NONNULL;
-LIQ_EXPORT LIQ_USERESULT int liq_image_get_height(const liq_image *img) LIQ_NONNULL;
-LIQ_EXPORT void liq_image_destroy(liq_image *img) LIQ_NONNULL;
-
-LIQ_EXPORT LIQ_USERESULT liq_error liq_histogram_quantize(liq_histogram *const input_hist, liq_attr *const options, liq_result **result_output) LIQ_NONNULL;
-LIQ_EXPORT LIQ_USERESULT liq_error liq_image_quantize(liq_image *const input_image, liq_attr *const options, liq_result **result_output) LIQ_NONNULL;
-
-LIQ_EXPORT liq_error liq_set_dithering_level(liq_result *res, float dither_level) LIQ_NONNULL;
-LIQ_EXPORT liq_error liq_set_output_gamma(liq_result* res, double gamma) LIQ_NONNULL;
-LIQ_EXPORT LIQ_USERESULT double liq_get_output_gamma(const liq_result *result) LIQ_NONNULL;
-
-LIQ_EXPORT LIQ_USERESULT const liq_palette *liq_get_palette(liq_result *result) LIQ_NONNULL;
-
-LIQ_EXPORT liq_error liq_write_remapped_image(liq_result *result, liq_image *input_image, void *buffer, size_t buffer_size) LIQ_NONNULL;
-LIQ_EXPORT liq_error liq_write_remapped_image_rows(liq_result *result, liq_image *input_image, unsigned char **row_pointers) LIQ_NONNULL;
-
-LIQ_EXPORT double liq_get_quantization_error(const liq_result *result) LIQ_NONNULL;
-LIQ_EXPORT int liq_get_quantization_quality(const liq_result *result) LIQ_NONNULL;
-LIQ_EXPORT double liq_get_remapping_error(const liq_result *result) LIQ_NONNULL;
-LIQ_EXPORT int liq_get_remapping_quality(const liq_result *result) LIQ_NONNULL;
-
-LIQ_EXPORT void liq_result_destroy(liq_result *) LIQ_NONNULL;
-
-LIQ_EXPORT int liq_version(void);
-
-
-// Deprecated
-LIQ_EXPORT LIQ_USERESULT liq_result *liq_quantize_image(liq_attr *options, liq_image *input_image) LIQ_NONNULL;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/vendor/code.ivysaur.me/imagequant/mediancut.c b/vendor/code.ivysaur.me/imagequant/mediancut.c
deleted file mode 100644
index 447a4af..0000000
--- a/vendor/code.ivysaur.me/imagequant/mediancut.c
+++ /dev/null
@@ -1,469 +0,0 @@
-/*
-** © 2009-2018 by Kornel Lesiński.
-** © 1989, 1991 by Jef Poskanzer.
-** © 1997, 2000, 2002 by Greg Roelofs; based on an idea by Stefan Schneider.
-**
-** See COPYRIGHT file for license.
-*/
-
-#include
-#include
-
-#include "libimagequant.h"
-#include "pam.h"
-#include "mediancut.h"
-
-#define index_of_channel(ch) (offsetof(f_pixel,ch)/sizeof(float))
-
-static f_pixel averagepixels(unsigned int clrs, const hist_item achv[]);
-
-struct box {
- f_pixel color;
- f_pixel variance;
- double sum, total_error, max_error;
- unsigned int ind;
- unsigned int colors;
-};
-
-ALWAYS_INLINE static double variance_diff(double val, const double good_enough);
-inline static double variance_diff(double val, const double good_enough)
-{
- val *= val;
- if (val < good_enough*good_enough) return val*0.25;
- return val;
-}
-
-/** Weighted per-channel variance of the box. It's used to decide which channel to split by */
-static f_pixel box_variance(const hist_item achv[], const struct box *box)
-{
- f_pixel mean = box->color;
- double variancea=0, variancer=0, varianceg=0, varianceb=0;
-
- for(unsigned int i = 0; i < box->colors; ++i) {
- const f_pixel px = achv[box->ind + i].acolor;
- double weight = achv[box->ind + i].adjusted_weight;
- variancea += variance_diff(mean.a - px.a, 2.0/256.0)*weight;
- variancer += variance_diff(mean.r - px.r, 1.0/256.0)*weight;
- varianceg += variance_diff(mean.g - px.g, 1.0/256.0)*weight;
- varianceb += variance_diff(mean.b - px.b, 1.0/256.0)*weight;
- }
-
- return (f_pixel){
- .a = variancea*(4.0/16.0),
- .r = variancer*(7.0/16.0),
- .g = varianceg*(9.0/16.0),
- .b = varianceb*(5.0/16.0),
- };
-}
-
-static double box_max_error(const hist_item achv[], const struct box *box)
-{
- f_pixel mean = box->color;
- double max_error = 0;
-
- for(unsigned int i = 0; i < box->colors; ++i) {
- const double diff = colordifference(mean, achv[box->ind + i].acolor);
- if (diff > max_error) {
- max_error = diff;
- }
- }
- return max_error;
-}
-
-ALWAYS_INLINE static double color_weight(f_pixel median, hist_item h);
-
-static inline void hist_item_swap(hist_item *l, hist_item *r)
-{
- if (l != r) {
- hist_item t = *l;
- *l = *r;
- *r = t;
- }
-}
-
-ALWAYS_INLINE static unsigned int qsort_pivot(const hist_item *const base, const unsigned int len);
-inline static unsigned int qsort_pivot(const hist_item *const base, const unsigned int len)
-{
- if (len < 32) {
- return len/2;
- }
-
- const unsigned int aidx=8, bidx=len/2, cidx=len-1;
- const unsigned int a=base[aidx].tmp.sort_value, b=base[bidx].tmp.sort_value, c=base[cidx].tmp.sort_value;
- return (a < b) ? ((b < c) ? bidx : ((a < c) ? cidx : aidx ))
- : ((b > c) ? bidx : ((a < c) ? aidx : cidx ));
-}
-
-ALWAYS_INLINE static unsigned int qsort_partition(hist_item *const base, const unsigned int len);
-inline static unsigned int qsort_partition(hist_item *const base, const unsigned int len)
-{
- unsigned int l = 1, r = len;
- if (len >= 8) {
- hist_item_swap(&base[0], &base[qsort_pivot(base,len)]);
- }
-
- const unsigned int pivot_value = base[0].tmp.sort_value;
- while (l < r) {
- if (base[l].tmp.sort_value >= pivot_value) {
- l++;
- } else {
- while(l < --r && base[r].tmp.sort_value <= pivot_value) {}
- hist_item_swap(&base[l], &base[r]);
- }
- }
- l--;
- hist_item_swap(&base[0], &base[l]);
-
- return l;
-}
-
-/** quick select algorithm */
-static void hist_item_sort_range(hist_item base[], unsigned int len, unsigned int sort_start)
-{
- for(;;) {
- const unsigned int l = qsort_partition(base, len), r = l+1;
-
- if (l > 0 && sort_start < l) {
- len = l;
- }
- else if (r < len && sort_start > r) {
- base += r; len -= r; sort_start -= r;
- }
- else break;
- }
-}
-
-/** sorts array to make sum of weights lower than halfvar one side, returns edge between halfvar parts of the set */
-static hist_item *hist_item_sort_halfvar(hist_item base[], unsigned int len, double *const lowervar, const double halfvar)
-{
- do {
- const unsigned int l = qsort_partition(base, len), r = l+1;
-
- // check if sum of left side is smaller than half,
- // if it is, then it doesn't need to be sorted
- unsigned int t = 0; double tmpsum = *lowervar;
- while (t <= l && tmpsum < halfvar) tmpsum += base[t++].color_weight;
-
- if (tmpsum < halfvar) {
- *lowervar = tmpsum;
- } else {
- if (l > 0) {
- hist_item *res = hist_item_sort_halfvar(base, l, lowervar, halfvar);
- if (res) return res;
- } else {
- // End of left recursion. This will be executed in order from the first element.
- *lowervar += base[0].color_weight;
- if (*lowervar > halfvar) return &base[0];
- }
- }
-
- if (len > r) {
- base += r; len -= r; // tail-recursive "call"
- } else {
- *lowervar += base[r].color_weight;
- return (*lowervar > halfvar) ? &base[r] : NULL;
- }
- } while(1);
-}
-
-static f_pixel get_median(const struct box *b, hist_item achv[]);
-
-typedef struct {
- unsigned int chan; float variance;
-} channelvariance;
-
-static int comparevariance(const void *ch1, const void *ch2)
-{
- return ((const channelvariance*)ch1)->variance > ((const channelvariance*)ch2)->variance ? -1 :
- (((const channelvariance*)ch1)->variance < ((const channelvariance*)ch2)->variance ? 1 : 0);
-}
-
-/** Finds which channels need to be sorted first and preproceses achv for fast sort */
-static double prepare_sort(struct box *b, hist_item achv[])
-{
- /*
- ** Sort dimensions by their variance, and then sort colors first by dimension with highest variance
- */
- channelvariance channels[4] = {
- {index_of_channel(a), b->variance.a},
- {index_of_channel(r), b->variance.r},
- {index_of_channel(g), b->variance.g},
- {index_of_channel(b), b->variance.b},
- };
-
- qsort(channels, 4, sizeof(channels[0]), comparevariance);
-
- const unsigned int ind1 = b->ind;
- const unsigned int colors = b->colors;
- #pragma omp parallel for if (colors > 25000) \
- schedule(static) default(none) shared(achv, channels)
- for(unsigned int i=0; i < colors; i++) {
- const float *chans = (const float *)&achv[ind1 + i].acolor;
- // Only the first channel really matters. When trying median cut many times
- // with different histogram weights, I don't want sort randomness to influence outcome.
- achv[ind1 + i].tmp.sort_value = ((unsigned int)(chans[channels[0].chan]*65535.0)<<16) |
- (unsigned int)((chans[channels[2].chan] + chans[channels[1].chan]/2.0 + chans[channels[3].chan]/4.0)*65535.0);
- }
-
- const f_pixel median = get_median(b, achv);
-
- // box will be split to make color_weight of each side even
- const unsigned int ind = b->ind, end = ind+b->colors;
- double totalvar = 0;
- #pragma omp parallel for if (end - ind > 15000) \
- schedule(static) default(shared) reduction(+:totalvar)
- for(unsigned int j=ind; j < end; j++) totalvar += (achv[j].color_weight = color_weight(median, achv[j]));
- return totalvar / 2.0;
-}
-
-/** finds median in unsorted set by sorting only minimum required */
-static f_pixel get_median(const struct box *b, hist_item achv[])
-{
- const unsigned int median_start = (b->colors-1)/2;
-
- hist_item_sort_range(&(achv[b->ind]), b->colors,
- median_start);
-
- if (b->colors&1) return achv[b->ind + median_start].acolor;
-
- // technically the second color is not guaranteed to be sorted correctly
- // but most of the time it is good enough to be useful
- return averagepixels(2, &achv[b->ind + median_start]);
-}
-
-/*
- ** Find the best splittable box. -1 if no boxes are splittable.
- */
-static int best_splittable_box(struct box bv[], unsigned int boxes, const double max_mse)
-{
- int bi=-1; double maxsum=0;
- for(unsigned int i=0; i < boxes; i++) {
- if (bv[i].colors < 2) {
- continue;
- }
-
- // looks only at max variance, because it's only going to split by it
- const double cv = MAX(bv[i].variance.r, MAX(bv[i].variance.g,bv[i].variance.b));
- double thissum = bv[i].sum * MAX(bv[i].variance.a, cv);
-
- if (bv[i].max_error > max_mse) {
- thissum = thissum* bv[i].max_error/max_mse;
- }
-
- if (thissum > maxsum) {
- maxsum = thissum;
- bi = i;
- }
- }
- return bi;
-}
-
-inline static double color_weight(f_pixel median, hist_item h)
-{
- float diff = colordifference(median, h.acolor);
- return sqrt(diff) * (sqrt(1.0+h.adjusted_weight)-1.0);
-}
-
-static void set_colormap_from_boxes(colormap *map, struct box bv[], unsigned int boxes, hist_item *achv);
-static void adjust_histogram(hist_item *achv, const struct box bv[], unsigned int boxes);
-
-static double box_error(const struct box *box, const hist_item achv[])
-{
- f_pixel avg = box->color;
-
- double total_error=0;
- for (unsigned int i = 0; i < box->colors; ++i) {
- total_error += colordifference(avg, achv[box->ind + i].acolor) * achv[box->ind + i].perceptual_weight;
- }
-
- return total_error;
-}
-
-
-static bool total_box_error_below_target(double target_mse, struct box bv[], unsigned int boxes, const histogram *hist)
-{
- target_mse *= hist->total_perceptual_weight;
- double total_error=0;
-
- for(unsigned int i=0; i < boxes; i++) {
- // error is (re)calculated lazily
- if (bv[i].total_error >= 0) {
- total_error += bv[i].total_error;
- }
- if (total_error > target_mse) return false;
- }
-
- for(unsigned int i=0; i < boxes; i++) {
- if (bv[i].total_error < 0) {
- bv[i].total_error = box_error(&bv[i], hist->achv);
- total_error += bv[i].total_error;
- }
- if (total_error > target_mse) return false;
- }
-
- return true;
-}
-
-static void box_init(struct box *box, const hist_item *achv, const unsigned int ind, const unsigned int colors, const double sum) {
- box->ind = ind;
- box->colors = colors;
- box->sum = sum;
- box->total_error = -1;
-
- box->color = averagepixels(colors, &achv[ind]);
- #pragma omp task if (colors > 5000)
- box->variance = box_variance(achv, box);
- #pragma omp task if (colors > 8000)
- box->max_error = box_max_error(achv, box);
-}
-
-/*
- ** Here is the fun part, the median-cut colormap generator. This is based
- ** on Paul Heckbert's paper, "Color Image Quantization for Frame Buffer
- ** Display," SIGGRAPH 1982 Proceedings, page 297.
- */
-LIQ_PRIVATE colormap *mediancut(histogram *hist, unsigned int newcolors, const double target_mse, const double max_mse, void* (*malloc)(size_t), void (*free)(void*))
-{
- hist_item *achv = hist->achv;
- LIQ_ARRAY(struct box, bv, newcolors);
- unsigned int boxes = 1;
-
- /*
- ** Set up the initial box.
- */
- #pragma omp parallel
- #pragma omp single
- {
- double sum = 0;
- for(unsigned int i=0; i < hist->size; i++) {
- sum += achv[i].adjusted_weight;
- }
- #pragma omp taskgroup
- {
- box_init(&bv[0], achv, 0, hist->size, sum);
- }
-
-
- /*
- ** Main loop: split boxes until we have enough.
- */
- while (boxes < newcolors) {
-
- // first splits boxes that exceed quality limit (to have colors for things like odd green pixel),
- // later raises the limit to allow large smooth areas/gradients get colors.
- const double current_max_mse = max_mse + (boxes/(double)newcolors)*16.0*max_mse;
- const int bi = best_splittable_box(bv, boxes, current_max_mse);
- if (bi < 0) {
- break; /* ran out of colors! */
- }
-
- unsigned int indx = bv[bi].ind;
- unsigned int clrs = bv[bi].colors;
-
- /*
- Classic implementation tries to get even number of colors or pixels in each subdivision.
-
- Here, instead of popularity I use (sqrt(popularity)*variance) metric.
- Each subdivision balances number of pixels (popular colors) and low variance -
- boxes can be large if they have similar colors. Later boxes with high variance
- will be more likely to be split.
-
- Median used as expected value gives much better results than mean.
- */
-
- const double halfvar = prepare_sort(&bv[bi], achv);
- double lowervar=0;
-
- // hist_item_sort_halfvar sorts and sums lowervar at the same time
- // returns item to break at …minus one, which does smell like an off-by-one error.
- hist_item *break_p = hist_item_sort_halfvar(&achv[indx], clrs, &lowervar, halfvar);
- unsigned int break_at = MIN(clrs-1, break_p - &achv[indx] + 1);
-
- /*
- ** Split the box.
- */
- double sm = bv[bi].sum;
- double lowersum = 0;
- for(unsigned int i=0; i < break_at; i++) lowersum += achv[indx + i].adjusted_weight;
-
- #pragma omp taskgroup
- {
- box_init(&bv[bi], achv, indx, break_at, lowersum);
- box_init(&bv[boxes], achv, indx + break_at, clrs - break_at, sm - lowersum);
- }
-
- ++boxes;
-
- if (total_box_error_below_target(target_mse, bv, boxes, hist)) {
- break;
- }
- }
- }
-
- colormap *map = pam_colormap(boxes, malloc, free);
- set_colormap_from_boxes(map, bv, boxes, achv);
-
- adjust_histogram(achv, bv, boxes);
-
- return map;
-}
-
-static void set_colormap_from_boxes(colormap *map, struct box* bv, unsigned int boxes, hist_item *achv)
-{
- /*
- ** Ok, we've got enough boxes. Now choose a representative color for
- ** each box. There are a number of possible ways to make this choice.
- ** One would be to choose the center of the box; this ignores any structure
- ** within the boxes. Another method would be to average all the colors in
- ** the box - this is the method specified in Heckbert's paper.
- */
-
- for(unsigned int bi = 0; bi < boxes; ++bi) {
- map->palette[bi].acolor = bv[bi].color;
-
- /* store total color popularity (perceptual_weight is approximation of it) */
- map->palette[bi].popularity = 0;
- for(unsigned int i=bv[bi].ind; i < bv[bi].ind+bv[bi].colors; i++) {
- map->palette[bi].popularity += achv[i].perceptual_weight;
- }
- }
-}
-
-/* increase histogram popularity by difference from the final color (this is used as part of feedback loop) */
-static void adjust_histogram(hist_item *achv, const struct box* bv, unsigned int boxes)
-{
- for(unsigned int bi = 0; bi < boxes; ++bi) {
- for(unsigned int i=bv[bi].ind; i < bv[bi].ind+bv[bi].colors; i++) {
- achv[i].tmp.likely_colormap_index = bi;
- }
- }
-}
-
-static f_pixel averagepixels(unsigned int clrs, const hist_item achv[])
-{
- double r = 0, g = 0, b = 0, a = 0, sum = 0;
-
- #pragma omp parallel for if (clrs > 25000) \
- schedule(static) default(shared) reduction(+:a) reduction(+:r) reduction(+:g) reduction(+:b) reduction(+:sum)
- for(unsigned int i = 0; i < clrs; i++) {
- const f_pixel px = achv[i].acolor;
- const double weight = achv[i].adjusted_weight;
-
- sum += weight;
- a += px.a * weight;
- r += px.r * weight;
- g += px.g * weight;
- b += px.b * weight;
- }
-
- if (sum) {
- a /= sum;
- r /= sum;
- g /= sum;
- b /= sum;
- }
-
- assert(!isnan(r) && !isnan(g) && !isnan(b) && !isnan(a));
-
- return (f_pixel){.r=r, .g=g, .b=b, .a=a};
-}
diff --git a/vendor/code.ivysaur.me/imagequant/mediancut.h b/vendor/code.ivysaur.me/imagequant/mediancut.h
deleted file mode 100644
index d97696c..0000000
--- a/vendor/code.ivysaur.me/imagequant/mediancut.h
+++ /dev/null
@@ -1,2 +0,0 @@
-
-LIQ_PRIVATE colormap *mediancut(histogram *hist, unsigned int newcolors, const double target_mse, const double max_mse, void* (*malloc)(size_t), void (*free)(void*));
diff --git a/vendor/code.ivysaur.me/imagequant/mempool.c b/vendor/code.ivysaur.me/imagequant/mempool.c
deleted file mode 100644
index cd49f59..0000000
--- a/vendor/code.ivysaur.me/imagequant/mempool.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
-** © 2009-2017 by Kornel Lesiński.
-** © 1989, 1991 by Jef Poskanzer.
-** © 1997, 2000, 2002 by Greg Roelofs; based on an idea by Stefan Schneider.
-**
-** See COPYRIGHT file for license.
-*/
-
-#include "libimagequant.h"
-#include "mempool.h"
-#include
-#include
-#include
-
-#define ALIGN_MASK 15UL
-#define MEMPOOL_RESERVED ((sizeof(struct mempool)+ALIGN_MASK) & ~ALIGN_MASK)
-
-struct mempool {
- unsigned int used, size;
- void* (*malloc)(size_t);
- void (*free)(void*);
- struct mempool *next;
-};
-LIQ_PRIVATE void* mempool_create(mempoolptr *mptr, const unsigned int size, unsigned int max_size, void* (*malloc)(size_t), void (*free)(void*))
-{
- if (*mptr && ((*mptr)->used+size) <= (*mptr)->size) {
- unsigned int prevused = (*mptr)->used;
- (*mptr)->used += (size+15UL) & ~0xFUL;
- return ((char*)(*mptr)) + prevused;
- }
-
- mempoolptr old = *mptr;
- if (!max_size) max_size = (1<<17);
- max_size = size+ALIGN_MASK > max_size ? size+ALIGN_MASK : max_size;
-
- *mptr = malloc(MEMPOOL_RESERVED + max_size);
- if (!*mptr) return NULL;
- **mptr = (struct mempool){
- .malloc = malloc,
- .free = free,
- .size = MEMPOOL_RESERVED + max_size,
- .used = sizeof(struct mempool),
- .next = old,
- };
- uintptr_t mptr_used_start = (uintptr_t)(*mptr) + (*mptr)->used;
- (*mptr)->used += (ALIGN_MASK + 1 - (mptr_used_start & ALIGN_MASK)) & ALIGN_MASK; // reserve bytes required to make subsequent allocations aligned
- assert(!(((uintptr_t)(*mptr) + (*mptr)->used) & ALIGN_MASK));
-
- return mempool_alloc(mptr, size, size);
-}
-
-LIQ_PRIVATE void* mempool_alloc(mempoolptr *mptr, const unsigned int size, const unsigned int max_size)
-{
- if (((*mptr)->used+size) <= (*mptr)->size) {
- unsigned int prevused = (*mptr)->used;
- (*mptr)->used += (size + ALIGN_MASK) & ~ALIGN_MASK;
- return ((char*)(*mptr)) + prevused;
- }
-
- return mempool_create(mptr, size, max_size, (*mptr)->malloc, (*mptr)->free);
-}
-
-LIQ_PRIVATE void mempool_destroy(mempoolptr m)
-{
- while (m) {
- mempoolptr next = m->next;
- m->free(m);
- m = next;
- }
-}
diff --git a/vendor/code.ivysaur.me/imagequant/mempool.h b/vendor/code.ivysaur.me/imagequant/mempool.h
deleted file mode 100644
index 9b7333b..0000000
--- a/vendor/code.ivysaur.me/imagequant/mempool.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef MEMPOOL_H
-#define MEMPOOL_H
-
-#include
-
-struct mempool;
-typedef struct mempool *mempoolptr;
-
-LIQ_PRIVATE void* mempool_create(mempoolptr *mptr, const unsigned int size, unsigned int capacity, void* (*malloc)(size_t), void (*free)(void*));
-LIQ_PRIVATE void* mempool_alloc(mempoolptr *mptr, const unsigned int size, const unsigned int capacity);
-LIQ_PRIVATE void mempool_destroy(mempoolptr m);
-
-#endif
diff --git a/vendor/code.ivysaur.me/imagequant/nearest.c b/vendor/code.ivysaur.me/imagequant/nearest.c
deleted file mode 100644
index aeb4dc1..0000000
--- a/vendor/code.ivysaur.me/imagequant/nearest.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
-** © 2009-2015 by Kornel Lesiński.
-** © 1989, 1991 by Jef Poskanzer.
-** © 1997, 2000, 2002 by Greg Roelofs; based on an idea by Stefan Schneider.
-**
-** See COPYRIGHT file for license.
-*/
-
-#include "libimagequant.h"
-#include "pam.h"
-#include "nearest.h"
-#include "mempool.h"
-#include
-
-typedef struct vp_sort_tmp {
- float distance_squared;
- unsigned int idx;
-} vp_sort_tmp;
-
-typedef struct vp_search_tmp {
- float distance;
- unsigned int idx;
- int exclude;
-} vp_search_tmp;
-
-typedef struct vp_node {
- struct vp_node *near, *far;
- f_pixel vantage_point;
- float radius;
- unsigned int idx;
-} vp_node;
-
-struct nearest_map {
- vp_node *root;
- const colormap_item *palette;
- float nearest_other_color_dist[256];
- mempoolptr mempool;
-};
-
-static void vp_search_node(const vp_node *node, const f_pixel *const needle, vp_search_tmp *const best_candidate);
-
-static int vp_compare_distance(const void *ap, const void *bp) {
- float a = ((const vp_sort_tmp*)ap)->distance_squared;
- float b = ((const vp_sort_tmp*)bp)->distance_squared;
- return a > b ? 1 : -1;
-}
-
-static void vp_sort_indexes_by_distance(const f_pixel vantage_point, vp_sort_tmp indexes[], int num_indexes, const colormap_item items[]) {
- for(int i=0; i < num_indexes; i++) {
- indexes[i].distance_squared = colordifference(vantage_point, items[indexes[i].idx].acolor);
- }
- qsort(indexes, num_indexes, sizeof(indexes[0]), vp_compare_distance);
-}
-
-/*
- * Usually it should pick farthest point, but picking most popular point seems to make search quicker anyway
- */
-static int vp_find_best_vantage_point_index(vp_sort_tmp indexes[], int num_indexes, const colormap_item items[]) {
- int best = 0;
- float best_popularity = items[indexes[0].idx].popularity;
- for(int i = 1; i < num_indexes; i++) {
- if (items[indexes[i].idx].popularity > best_popularity) {
- best_popularity = items[indexes[i].idx].popularity;
- best = i;
- }
- }
- return best;
-}
-
-static vp_node *vp_create_node(mempoolptr *m, vp_sort_tmp indexes[], int num_indexes, const colormap_item items[]) {
- if (num_indexes <= 0) {
- return NULL;
- }
-
- vp_node *node = mempool_alloc(m, sizeof(node[0]), 0);
-
- if (num_indexes == 1) {
- *node = (vp_node){
- .vantage_point = items[indexes[0].idx].acolor,
- .idx = indexes[0].idx,
- .radius = MAX_DIFF,
- };
- return node;
- }
-
- const int ref = vp_find_best_vantage_point_index(indexes, num_indexes, items);
- const int ref_idx = indexes[ref].idx;
-
- // Removes the `ref_idx` item from remaining items, because it's included in the current node
- num_indexes -= 1;
- indexes[ref] = indexes[num_indexes];
-
- vp_sort_indexes_by_distance(items[ref_idx].acolor, indexes, num_indexes, items);
-
- // Remaining items are split by the median distance
- const int half_idx = num_indexes/2;
-
- *node = (vp_node){
- .vantage_point = items[ref_idx].acolor,
- .idx = ref_idx,
- .radius = sqrtf(indexes[half_idx].distance_squared),
- };
- node->near = vp_create_node(m, indexes, half_idx, items);
- node->far = vp_create_node(m, &indexes[half_idx], num_indexes - half_idx, items);
-
- return node;
-}
-
-LIQ_PRIVATE struct nearest_map *nearest_init(const colormap *map) {
- mempoolptr m = NULL;
- struct nearest_map *handle = mempool_create(&m, sizeof(handle[0]), sizeof(handle[0]) + sizeof(vp_node)*map->colors+16, map->malloc, map->free);
-
- LIQ_ARRAY(vp_sort_tmp, indexes, map->colors);
-
- for(unsigned int i=0; i < map->colors; i++) {
- indexes[i].idx = i;
- }
-
- vp_node *root = vp_create_node(&m, indexes, map->colors, map->palette);
- *handle = (struct nearest_map){
- .root = root,
- .palette = map->palette,
- .mempool = m,
- };
-
- for(unsigned int i=0; i < map->colors; i++) {
- vp_search_tmp best = {
- .distance = MAX_DIFF,
- .exclude = i,
- };
- vp_search_node(root, &map->palette[i].acolor, &best);
- handle->nearest_other_color_dist[i] = best.distance * best.distance / 4.0; // half of squared distance
- }
-
- return handle;
-}
-
-static void vp_search_node(const vp_node *node, const f_pixel *const needle, vp_search_tmp *const best_candidate) {
- do {
- const float distance = sqrtf(colordifference(node->vantage_point, *needle));
-
- if (distance < best_candidate->distance && best_candidate->exclude != node->idx) {
- best_candidate->distance = distance;
- best_candidate->idx = node->idx;
- }
-
- // Recurse towards most likely candidate first to narrow best candidate's distance as soon as possible
- if (distance < node->radius) {
- if (node->near) {
- vp_search_node(node->near, needle, best_candidate);
- }
- // The best node (final answer) may be just ouside the radius, but not farther than
- // the best distance we know so far. The vp_search_node above should have narrowed
- // best_candidate->distance, so this path is rarely taken.
- if (node->far && distance >= node->radius - best_candidate->distance) {
- node = node->far; // Fast tail recursion
- } else {
- break;
- }
- } else {
- if (node->far) {
- vp_search_node(node->far, needle, best_candidate);
- }
- if (node->near && distance <= node->radius + best_candidate->distance) {
- node = node->near; // Fast tail recursion
- } else {
- break;
- }
- }
- } while(true);
-}
-
-LIQ_PRIVATE unsigned int nearest_search(const struct nearest_map *handle, const f_pixel *px, const int likely_colormap_index, float *diff) {
- const float guess_diff = colordifference(handle->palette[likely_colormap_index].acolor, *px);
- if (guess_diff < handle->nearest_other_color_dist[likely_colormap_index]) {
- if (diff) *diff = guess_diff;
- return likely_colormap_index;
- }
-
- vp_search_tmp best_candidate = {
- .distance = sqrtf(guess_diff),
- .idx = likely_colormap_index,
- .exclude = -1,
- };
- vp_search_node(handle->root, px, &best_candidate);
- if (diff) {
- *diff = best_candidate.distance * best_candidate.distance;
- }
- return best_candidate.idx;
-}
-
-LIQ_PRIVATE void nearest_free(struct nearest_map *centroids)
-{
- mempool_destroy(centroids->mempool);
-}
diff --git a/vendor/code.ivysaur.me/imagequant/nearest.h b/vendor/code.ivysaur.me/imagequant/nearest.h
deleted file mode 100644
index e20233b..0000000
--- a/vendor/code.ivysaur.me/imagequant/nearest.h
+++ /dev/null
@@ -1,8 +0,0 @@
-//
-// nearest.h
-// pngquant
-//
-struct nearest_map;
-LIQ_PRIVATE struct nearest_map *nearest_init(const colormap *palette);
-LIQ_PRIVATE unsigned int nearest_search(const struct nearest_map *map, const f_pixel *px, const int palette_index_guess, float *diff);
-LIQ_PRIVATE void nearest_free(struct nearest_map *map);
diff --git a/vendor/code.ivysaur.me/imagequant/pam.c b/vendor/code.ivysaur.me/imagequant/pam.c
deleted file mode 100644
index 660f829..0000000
--- a/vendor/code.ivysaur.me/imagequant/pam.c
+++ /dev/null
@@ -1,286 +0,0 @@
-/* pam.c - pam (portable alpha map) utility library
-**
-** © 2009-2017 by Kornel Lesiński.
-** © 1989, 1991 by Jef Poskanzer.
-** © 1997, 2000, 2002 by Greg Roelofs; based on an idea by Stefan Schneider.
-**
-** See COPYRIGHT file for license.
-*/
-
-#include
-#include
-
-#include "libimagequant.h"
-#include "pam.h"
-#include "mempool.h"
-
-LIQ_PRIVATE bool pam_computeacolorhash(struct acolorhash_table *acht, const rgba_pixel *const pixels[], unsigned int cols, unsigned int rows, const unsigned char *importance_map)
-{
- const unsigned int ignorebits = acht->ignorebits;
- const unsigned int channel_mask = 255U>>ignorebits<>ignorebits) ^ 0xFFU;
- const unsigned int posterize_mask = channel_mask << 24 | channel_mask << 16 | channel_mask << 8 | channel_mask;
- const unsigned int posterize_high_mask = channel_hmask << 24 | channel_hmask << 16 | channel_hmask << 8 | channel_hmask;
-
- const unsigned int hash_size = acht->hash_size;
-
- /* Go through the entire image, building a hash table of colors. */
- for(unsigned int row = 0; row < rows; ++row) {
-
- for(unsigned int col = 0; col < cols; ++col) {
- unsigned int boost;
-
- // RGBA color is casted to long for easier hasing/comparisons
- union rgba_as_int px = {pixels[row][col]};
- unsigned int hash;
- if (!px.rgba.a) {
- // "dirty alpha" has different RGBA values that end up being the same fully transparent color
- px.l=0; hash=0;
-
- boost = 2000;
- if (importance_map) {
- importance_map++;
- }
- } else {
- // mask posterizes all 4 channels in one go
- px.l = (px.l & posterize_mask) | ((px.l & posterize_high_mask) >> (8-ignorebits));
- // fancier hashing algorithms didn't improve much
- hash = px.l % hash_size;
-
- if (importance_map) {
- boost = *importance_map++;
- } else {
- boost = 255;
- }
- }
-
- if (!pam_add_to_hash(acht, hash, boost, px, row, rows)) {
- return false;
- }
- }
-
- }
- acht->cols = cols;
- acht->rows += rows;
- return true;
-}
-
-LIQ_PRIVATE bool pam_add_to_hash(struct acolorhash_table *acht, unsigned int hash, unsigned int boost, union rgba_as_int px, unsigned int row, unsigned int rows)
-{
- /* head of the hash function stores first 2 colors inline (achl->used = 1..2),
- to reduce number of allocations of achl->other_items.
- */
- struct acolorhist_arr_head *achl = &acht->buckets[hash];
- if (achl->inline1.color.l == px.l && achl->used) {
- achl->inline1.perceptual_weight += boost;
- return true;
- }
- if (achl->used) {
- if (achl->used > 1) {
- if (achl->inline2.color.l == px.l) {
- achl->inline2.perceptual_weight += boost;
- return true;
- }
- // other items are stored as an array (which gets reallocated if needed)
- struct acolorhist_arr_item *other_items = achl->other_items;
- unsigned int i = 0;
- for (; i < achl->used-2; i++) {
- if (other_items[i].color.l == px.l) {
- other_items[i].perceptual_weight += boost;
- return true;
- }
- }
-
- // the array was allocated with spare items
- if (i < achl->capacity) {
- other_items[i] = (struct acolorhist_arr_item){
- .color = px,
- .perceptual_weight = boost,
- };
- achl->used++;
- ++acht->colors;
- return true;
- }
-
- if (++acht->colors > acht->maxcolors) {
- return false;
- }
-
- struct acolorhist_arr_item *new_items;
- unsigned int capacity;
- if (!other_items) { // there was no array previously, alloc "small" array
- capacity = 8;
- if (acht->freestackp <= 0) {
- // estimate how many colors are going to be + headroom
- const size_t mempool_size = ((acht->rows + rows-row) * 2 * acht->colors / (acht->rows + row + 1) + 1024) * sizeof(struct acolorhist_arr_item);
- new_items = mempool_alloc(&acht->mempool, sizeof(struct acolorhist_arr_item)*capacity, mempool_size);
- } else {
- // freestack stores previously freed (reallocated) arrays that can be reused
- // (all pesimistically assumed to be capacity = 8)
- new_items = acht->freestack[--acht->freestackp];
- }
- } else {
- const unsigned int stacksize = sizeof(acht->freestack)/sizeof(acht->freestack[0]);
-
- // simply reallocs and copies array to larger capacity
- capacity = achl->capacity*2 + 16;
- if (acht->freestackp < stacksize-1) {
- acht->freestack[acht->freestackp++] = other_items;
- }
- const size_t mempool_size = ((acht->rows + rows-row) * 2 * acht->colors / (acht->rows + row + 1) + 32*capacity) * sizeof(struct acolorhist_arr_item);
- new_items = mempool_alloc(&acht->mempool, sizeof(struct acolorhist_arr_item)*capacity, mempool_size);
- if (!new_items) return false;
- memcpy(new_items, other_items, sizeof(other_items[0])*achl->capacity);
- }
-
- achl->other_items = new_items;
- achl->capacity = capacity;
- new_items[i] = (struct acolorhist_arr_item){
- .color = px,
- .perceptual_weight = boost,
- };
- achl->used++;
- } else {
- // these are elses for first checks whether first and second inline-stored colors are used
- achl->inline2.color.l = px.l;
- achl->inline2.perceptual_weight = boost;
- achl->used = 2;
- ++acht->colors;
- }
- } else {
- achl->inline1.color.l = px.l;
- achl->inline1.perceptual_weight = boost;
- achl->used = 1;
- ++acht->colors;
- }
- return true;
-}
-
-LIQ_PRIVATE struct acolorhash_table *pam_allocacolorhash(unsigned int maxcolors, unsigned int surface, unsigned int ignorebits, void* (*malloc)(size_t), void (*free)(void*))
-{
- const size_t estimated_colors = MIN(maxcolors, surface/(ignorebits + (surface > 512*512 ? 6 : 5)));
- const size_t hash_size = estimated_colors < 66000 ? 6673 : (estimated_colors < 200000 ? 12011 : 24019);
-
- mempoolptr m = NULL;
- const size_t buckets_size = hash_size * sizeof(struct acolorhist_arr_head);
- const size_t mempool_size = sizeof(struct acolorhash_table) + buckets_size + estimated_colors * sizeof(struct acolorhist_arr_item);
- struct acolorhash_table *t = mempool_create(&m, sizeof(*t) + buckets_size, mempool_size, malloc, free);
- if (!t) return NULL;
- *t = (struct acolorhash_table){
- .mempool = m,
- .hash_size = hash_size,
- .maxcolors = maxcolors,
- .ignorebits = ignorebits,
- };
- memset(t->buckets, 0, buckets_size);
- return t;
-}
-
-ALWAYS_INLINE static float pam_add_to_hist(const float *gamma_lut, hist_item *achv, unsigned int *j, const struct acolorhist_arr_item *entry, const float max_perceptual_weight)
-{
- if (entry->perceptual_weight == 0) {
- return 0;
- }
- const float w = MIN(entry->perceptual_weight/128.f, max_perceptual_weight);
- achv[*j].adjusted_weight = achv[*j].perceptual_weight = w;
- achv[*j].acolor = rgba_to_f(gamma_lut, entry->color.rgba);
- *j += 1;
- return w;
-}
-
-LIQ_PRIVATE histogram *pam_acolorhashtoacolorhist(const struct acolorhash_table *acht, const double gamma, void* (*malloc)(size_t), void (*free)(void*))
-{
- histogram *hist = malloc(sizeof(hist[0]));
- if (!hist || !acht) return NULL;
- *hist = (histogram){
- .achv = malloc(MAX(1,acht->colors) * sizeof(hist->achv[0])),
- .size = acht->colors,
- .free = free,
- .ignorebits = acht->ignorebits,
- };
- if (!hist->achv) return NULL;
-
- float gamma_lut[256];
- to_f_set_gamma(gamma_lut, gamma);
-
- /* Limit perceptual weight to 1/10th of the image surface area to prevent
- a single color from dominating all others. */
- float max_perceptual_weight = 0.1f * acht->cols * acht->rows;
- double total_weight = 0;
-
- unsigned int j=0;
- for(unsigned int i=0; i < acht->hash_size; ++i) {
- const struct acolorhist_arr_head *const achl = &acht->buckets[i];
- if (achl->used) {
- total_weight += pam_add_to_hist(gamma_lut, hist->achv, &j, &achl->inline1, max_perceptual_weight);
-
- if (achl->used > 1) {
- total_weight += pam_add_to_hist(gamma_lut, hist->achv, &j, &achl->inline2, max_perceptual_weight);
-
- for(unsigned int k=0; k < achl->used-2; k++) {
- total_weight += pam_add_to_hist(gamma_lut, hist->achv, &j, &achl->other_items[k], max_perceptual_weight);
- }
- }
- }
- }
- hist->size = j;
- hist->total_perceptual_weight = total_weight;
- if (!j) {
- pam_freeacolorhist(hist);
- return NULL;
- }
- return hist;
-}
-
-
-LIQ_PRIVATE void pam_freeacolorhash(struct acolorhash_table *acht)
-{
- if (acht) {
- mempool_destroy(acht->mempool);
- }
-}
-
-LIQ_PRIVATE void pam_freeacolorhist(histogram *hist)
-{
- hist->free(hist->achv);
- hist->free(hist);
-}
-
-LIQ_PRIVATE colormap *pam_colormap(unsigned int colors, void* (*malloc)(size_t), void (*free)(void*))
-{
- assert(colors > 0 && colors < 65536);
-
- colormap *map;
- const size_t colors_size = colors * sizeof(map->palette[0]);
- map = malloc(sizeof(colormap) + colors_size);
- if (!map) return NULL;
- *map = (colormap){
- .malloc = malloc,
- .free = free,
- .colors = colors,
- };
- memset(map->palette, 0, colors_size);
- return map;
-}
-
-LIQ_PRIVATE colormap *pam_duplicate_colormap(colormap *map)
-{
- colormap *dupe = pam_colormap(map->colors, map->malloc, map->free);
- for(unsigned int i=0; i < map->colors; i++) {
- dupe->palette[i] = map->palette[i];
- }
- return dupe;
-}
-
-LIQ_PRIVATE void pam_freecolormap(colormap *c)
-{
- c->free(c);
-}
-
-LIQ_PRIVATE void to_f_set_gamma(float gamma_lut[], const double gamma)
-{
- for(int i=0; i < 256; i++) {
- gamma_lut[i] = pow((double)i/255.0, internal_gamma/gamma);
- }
-}
-
diff --git a/vendor/code.ivysaur.me/imagequant/pam.h b/vendor/code.ivysaur.me/imagequant/pam.h
deleted file mode 100644
index 2ca4327..0000000
--- a/vendor/code.ivysaur.me/imagequant/pam.h
+++ /dev/null
@@ -1,277 +0,0 @@
-/* pam.h - pam (portable alpha map) utility library
- **
- ** Colormap routines.
- **
- ** Copyright (C) 1989, 1991 by Jef Poskanzer.
- ** Copyright (C) 1997 by Greg Roelofs.
- **
- ** Permission to use, copy, modify, and distribute this software and its
- ** documentation for any purpose and without fee is hereby granted, provided
- ** that the above copyright notice appear in all copies and that both that
- ** copyright notice and this permission notice appear in supporting
- ** documentation. This software is provided "as is" without express or
- ** implied warranty.
- */
-
-#ifndef PAM_H
-#define PAM_H
-
-#include
-#include
-#include
-#include
-
-#ifndef MAX
-# define MAX(a,b) ((a) > (b)? (a) : (b))
-# define MIN(a,b) ((a) < (b)? (a) : (b))
-#endif
-
-#define MAX_DIFF 1e20
-
-#ifndef USE_SSE
-# if defined(__SSE__) && (defined(__amd64__) || defined(__X86_64__) || defined(_WIN64) || defined(WIN32) || defined(__WIN32__))
-# define USE_SSE 1
-# else
-# define USE_SSE 0
-# endif
-#endif
-
-#if USE_SSE
-# include
-# ifdef _MSC_VER
-# include
-# define SSE_ALIGN
-# else
-# define SSE_ALIGN __attribute__ ((aligned (16)))
-# if defined(__i386__) && defined(__PIC__)
-# define cpuid(func,ax,bx,cx,dx)\
- __asm__ __volatile__ ( \
- "push %%ebx\n" \
- "cpuid\n" \
- "mov %%ebx, %1\n" \
- "pop %%ebx\n" \
- : "=a" (ax), "=r" (bx), "=c" (cx), "=d" (dx) \
- : "a" (func));
-# else
-# define cpuid(func,ax,bx,cx,dx)\
- __asm__ __volatile__ ("cpuid":\
- "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) : "a" (func));
-# endif
-#endif
-#else
-# define SSE_ALIGN
-#endif
-
-#ifndef _MSC_VER
-#define LIQ_ARRAY(type, var, count) type var[count]
-#else
-#define LIQ_ARRAY(type, var, count) type* var = (type*)_alloca(sizeof(type)*(count))
-#endif
-
-#if defined(__GNUC__) || defined (__llvm__)
-#define ALWAYS_INLINE __attribute__((always_inline)) inline
-#define NEVER_INLINE __attribute__ ((noinline))
-#elif defined(_MSC_VER)
-#define inline __inline
-#define restrict __restrict
-#define ALWAYS_INLINE __forceinline
-#define NEVER_INLINE __declspec(noinline)
-#else
-#define ALWAYS_INLINE inline
-#define NEVER_INLINE
-#endif
-
-/* from pam.h */
-
-typedef struct {
- unsigned char r, g, b, a;
-} rgba_pixel;
-
-typedef struct {
- float a, r, g, b;
-} SSE_ALIGN f_pixel;
-
-static const float internal_gamma = 0.5499f;
-
-LIQ_PRIVATE void to_f_set_gamma(float gamma_lut[], const double gamma);
-
-/**
- Converts 8-bit color to internal gamma and premultiplied alpha.
- (premultiplied color space is much better for blending of semitransparent colors)
- */
-ALWAYS_INLINE static f_pixel rgba_to_f(const float gamma_lut[], const rgba_pixel px);
-inline static f_pixel rgba_to_f(const float gamma_lut[], const rgba_pixel px)
-{
- float a = px.a/255.f;
-
- return (f_pixel) {
- .a = a,
- .r = gamma_lut[px.r]*a,
- .g = gamma_lut[px.g]*a,
- .b = gamma_lut[px.b]*a,
- };
-}
-
-inline static rgba_pixel f_to_rgb(const float gamma, const f_pixel px)
-{
- if (px.a < 1.f/256.f) {
- return (rgba_pixel){0,0,0,0};
- }
-
- float r = px.r / px.a,
- g = px.g / px.a,
- b = px.b / px.a,
- a = px.a;
-
- r = powf(r, gamma/internal_gamma);
- g = powf(g, gamma/internal_gamma);
- b = powf(b, gamma/internal_gamma);
-
- // 256, because numbers are in range 1..255.9999… rounded down
- r *= 256.f;
- g *= 256.f;
- b *= 256.f;
- a *= 256.f;
-
- return (rgba_pixel){
- .r = r>=255.f ? 255 : r,
- .g = g>=255.f ? 255 : g,
- .b = b>=255.f ? 255 : b,
- .a = a>=255.f ? 255 : a,
- };
-}
-
-ALWAYS_INLINE static double colordifference_ch(const double x, const double y, const double alphas);
-inline static double colordifference_ch(const double x, const double y, const double alphas)
-{
- // maximum of channel blended on white, and blended on black
- // premultiplied alpha and backgrounds 0/1 shorten the formula
- const double black = x-y, white = black+alphas;
- return MAX(black*black, white*white);
-}
-
-ALWAYS_INLINE static float colordifference_stdc(const f_pixel px, const f_pixel py);
-inline static float colordifference_stdc(const f_pixel px, const f_pixel py)
-{
- // px_b.rgb = px.rgb + 0*(1-px.a) // blend px on black
- // px_b.a = px.a + 1*(1-px.a)
- // px_w.rgb = px.rgb + 1*(1-px.a) // blend px on white
- // px_w.a = px.a + 1*(1-px.a)
-
- // px_b.rgb = px.rgb // difference same as in opaque RGB
- // px_b.a = 1
- // px_w.rgb = px.rgb - px.a // difference simplifies to formula below
- // px_w.a = 1
-
- // (px.rgb - px.a) - (py.rgb - py.a)
- // (px.rgb - py.rgb) + (py.a - px.a)
-
- const double alphas = py.a-px.a;
- return colordifference_ch(px.r, py.r, alphas) +
- colordifference_ch(px.g, py.g, alphas) +
- colordifference_ch(px.b, py.b, alphas);
-}
-
-ALWAYS_INLINE static float colordifference(f_pixel px, f_pixel py);
-inline static float colordifference(f_pixel px, f_pixel py)
-{
-#if USE_SSE
- const __m128 vpx = _mm_load_ps((const float*)&px);
- const __m128 vpy = _mm_load_ps((const float*)&py);
-
- // y.a - x.a
- __m128 alphas = _mm_sub_ss(vpy, vpx);
- alphas = _mm_shuffle_ps(alphas,alphas,0); // copy first to all four
-
- __m128 onblack = _mm_sub_ps(vpx, vpy); // x - y
- __m128 onwhite = _mm_add_ps(onblack, alphas); // x - y + (y.a - x.a)
-
- onblack = _mm_mul_ps(onblack, onblack);
- onwhite = _mm_mul_ps(onwhite, onwhite);
- const __m128 max = _mm_max_ps(onwhite, onblack);
-
- // add rgb, not a
- const __m128 maxhl = _mm_movehl_ps(max, max);
- const __m128 tmp = _mm_add_ps(max, maxhl);
- const __m128 sum = _mm_add_ss(maxhl, _mm_shuffle_ps(tmp, tmp, 1));
-
- const float res = _mm_cvtss_f32(sum);
- assert(fabs(res - colordifference_stdc(px,py)) < 0.001);
- return res;
-#else
- return colordifference_stdc(px,py);
-#endif
-}
-
-/* from pamcmap.h */
-union rgba_as_int {
- rgba_pixel rgba;
- unsigned int l;
-};
-
-typedef struct {
- f_pixel acolor;
- float adjusted_weight, // perceptual weight changed to tweak how mediancut selects colors
- perceptual_weight; // number of pixels weighted by importance of different areas of the picture
-
- float color_weight; // these two change every time histogram subset is sorted
- union {
- unsigned int sort_value;
- unsigned char likely_colormap_index;
- } tmp;
-} hist_item;
-
-typedef struct {
- hist_item *achv;
- void (*free)(void*);
- double total_perceptual_weight;
- unsigned int size;
- unsigned int ignorebits;
-} histogram;
-
-typedef struct {
- f_pixel acolor;
- float popularity;
- bool fixed; // if true it's user-supplied and must not be changed (e.g in K-Means iteration)
-} colormap_item;
-
-typedef struct colormap {
- unsigned int colors;
- void* (*malloc)(size_t);
- void (*free)(void*);
- colormap_item palette[];
-} colormap;
-
-struct acolorhist_arr_item {
- union rgba_as_int color;
- unsigned int perceptual_weight;
-};
-
-struct acolorhist_arr_head {
- struct acolorhist_arr_item inline1, inline2;
- unsigned int used, capacity;
- struct acolorhist_arr_item *other_items;
-};
-
-struct acolorhash_table {
- struct mempool *mempool;
- unsigned int ignorebits, maxcolors, colors, cols, rows;
- unsigned int hash_size;
- unsigned int freestackp;
- struct acolorhist_arr_item *freestack[512];
- struct acolorhist_arr_head buckets[];
-};
-
-LIQ_PRIVATE void pam_freeacolorhash(struct acolorhash_table *acht);
-LIQ_PRIVATE struct acolorhash_table *pam_allocacolorhash(unsigned int maxcolors, unsigned int surface, unsigned int ignorebits, void* (*malloc)(size_t), void (*free)(void*));
-LIQ_PRIVATE histogram *pam_acolorhashtoacolorhist(const struct acolorhash_table *acht, const double gamma, void* (*malloc)(size_t), void (*free)(void*));
-LIQ_PRIVATE bool pam_computeacolorhash(struct acolorhash_table *acht, const rgba_pixel *const pixels[], unsigned int cols, unsigned int rows, const unsigned char *importance_map);
-LIQ_PRIVATE bool pam_add_to_hash(struct acolorhash_table *acht, unsigned int hash, unsigned int boost, union rgba_as_int px, unsigned int row, unsigned int rows);
-
-LIQ_PRIVATE void pam_freeacolorhist(histogram *h);
-
-LIQ_PRIVATE colormap *pam_colormap(unsigned int colors, void* (*malloc)(size_t), void (*free)(void*));
-LIQ_PRIVATE colormap *pam_duplicate_colormap(colormap *map);
-LIQ_PRIVATE void pam_freecolormap(colormap *c);
-
-#endif
diff --git a/vendor/github.com/hashicorp/golang-lru/.gitignore b/vendor/github.com/hashicorp/golang-lru/.gitignore
deleted file mode 100644
index 8365624..0000000
--- a/vendor/github.com/hashicorp/golang-lru/.gitignore
+++ /dev/null
@@ -1,23 +0,0 @@
-# Compiled Object files, Static and Dynamic libs (Shared Objects)
-*.o
-*.a
-*.so
-
-# Folders
-_obj
-_test
-
-# Architecture specific extensions/prefixes
-*.[568vq]
-[568vq].out
-
-*.cgo1.go
-*.cgo2.c
-_cgo_defun.c
-_cgo_gotypes.go
-_cgo_export.*
-
-_testmain.go
-
-*.exe
-*.test
diff --git a/vendor/github.com/hashicorp/golang-lru/2q.go b/vendor/github.com/hashicorp/golang-lru/2q.go
deleted file mode 100644
index e474cd0..0000000
--- a/vendor/github.com/hashicorp/golang-lru/2q.go
+++ /dev/null
@@ -1,223 +0,0 @@
-package lru
-
-import (
- "fmt"
- "sync"
-
- "github.com/hashicorp/golang-lru/simplelru"
-)
-
-const (
- // Default2QRecentRatio is the ratio of the 2Q cache dedicated
- // to recently added entries that have only been accessed once.
- Default2QRecentRatio = 0.25
-
- // Default2QGhostEntries is the default ratio of ghost
- // entries kept to track entries recently evicted
- Default2QGhostEntries = 0.50
-)
-
-// TwoQueueCache is a thread-safe fixed size 2Q cache.
-// 2Q is an enhancement over the standard LRU cache
-// in that it tracks both frequently and recently used
-// entries separately. This avoids a burst in access to new
-// entries from evicting frequently used entries. It adds some
-// additional tracking overhead to the standard LRU cache, and is
-// computationally about 2x the cost, and adds some metadata over
-// head. The ARCCache is similar, but does not require setting any
-// parameters.
-type TwoQueueCache struct {
- size int
- recentSize int
-
- recent simplelru.LRUCache
- frequent simplelru.LRUCache
- recentEvict simplelru.LRUCache
- lock sync.RWMutex
-}
-
-// New2Q creates a new TwoQueueCache using the default
-// values for the parameters.
-func New2Q(size int) (*TwoQueueCache, error) {
- return New2QParams(size, Default2QRecentRatio, Default2QGhostEntries)
-}
-
-// New2QParams creates a new TwoQueueCache using the provided
-// parameter values.
-func New2QParams(size int, recentRatio float64, ghostRatio float64) (*TwoQueueCache, error) {
- if size <= 0 {
- return nil, fmt.Errorf("invalid size")
- }
- if recentRatio < 0.0 || recentRatio > 1.0 {
- return nil, fmt.Errorf("invalid recent ratio")
- }
- if ghostRatio < 0.0 || ghostRatio > 1.0 {
- return nil, fmt.Errorf("invalid ghost ratio")
- }
-
- // Determine the sub-sizes
- recentSize := int(float64(size) * recentRatio)
- evictSize := int(float64(size) * ghostRatio)
-
- // Allocate the LRUs
- recent, err := simplelru.NewLRU(size, nil)
- if err != nil {
- return nil, err
- }
- frequent, err := simplelru.NewLRU(size, nil)
- if err != nil {
- return nil, err
- }
- recentEvict, err := simplelru.NewLRU(evictSize, nil)
- if err != nil {
- return nil, err
- }
-
- // Initialize the cache
- c := &TwoQueueCache{
- size: size,
- recentSize: recentSize,
- recent: recent,
- frequent: frequent,
- recentEvict: recentEvict,
- }
- return c, nil
-}
-
-// Get looks up a key's value from the cache.
-func (c *TwoQueueCache) Get(key interface{}) (value interface{}, ok bool) {
- c.lock.Lock()
- defer c.lock.Unlock()
-
- // Check if this is a frequent value
- if val, ok := c.frequent.Get(key); ok {
- return val, ok
- }
-
- // If the value is contained in recent, then we
- // promote it to frequent
- if val, ok := c.recent.Peek(key); ok {
- c.recent.Remove(key)
- c.frequent.Add(key, val)
- return val, ok
- }
-
- // No hit
- return nil, false
-}
-
-// Add adds a value to the cache.
-func (c *TwoQueueCache) Add(key, value interface{}) {
- c.lock.Lock()
- defer c.lock.Unlock()
-
- // Check if the value is frequently used already,
- // and just update the value
- if c.frequent.Contains(key) {
- c.frequent.Add(key, value)
- return
- }
-
- // Check if the value is recently used, and promote
- // the value into the frequent list
- if c.recent.Contains(key) {
- c.recent.Remove(key)
- c.frequent.Add(key, value)
- return
- }
-
- // If the value was recently evicted, add it to the
- // frequently used list
- if c.recentEvict.Contains(key) {
- c.ensureSpace(true)
- c.recentEvict.Remove(key)
- c.frequent.Add(key, value)
- return
- }
-
- // Add to the recently seen list
- c.ensureSpace(false)
- c.recent.Add(key, value)
- return
-}
-
-// ensureSpace is used to ensure we have space in the cache
-func (c *TwoQueueCache) ensureSpace(recentEvict bool) {
- // If we have space, nothing to do
- recentLen := c.recent.Len()
- freqLen := c.frequent.Len()
- if recentLen+freqLen < c.size {
- return
- }
-
- // If the recent buffer is larger than
- // the target, evict from there
- if recentLen > 0 && (recentLen > c.recentSize || (recentLen == c.recentSize && !recentEvict)) {
- k, _, _ := c.recent.RemoveOldest()
- c.recentEvict.Add(k, nil)
- return
- }
-
- // Remove from the frequent list otherwise
- c.frequent.RemoveOldest()
-}
-
-// Len returns the number of items in the cache.
-func (c *TwoQueueCache) Len() int {
- c.lock.RLock()
- defer c.lock.RUnlock()
- return c.recent.Len() + c.frequent.Len()
-}
-
-// Keys returns a slice of the keys in the cache.
-// The frequently used keys are first in the returned slice.
-func (c *TwoQueueCache) Keys() []interface{} {
- c.lock.RLock()
- defer c.lock.RUnlock()
- k1 := c.frequent.Keys()
- k2 := c.recent.Keys()
- return append(k1, k2...)
-}
-
-// Remove removes the provided key from the cache.
-func (c *TwoQueueCache) Remove(key interface{}) {
- c.lock.Lock()
- defer c.lock.Unlock()
- if c.frequent.Remove(key) {
- return
- }
- if c.recent.Remove(key) {
- return
- }
- if c.recentEvict.Remove(key) {
- return
- }
-}
-
-// Purge is used to completely clear the cache.
-func (c *TwoQueueCache) Purge() {
- c.lock.Lock()
- defer c.lock.Unlock()
- c.recent.Purge()
- c.frequent.Purge()
- c.recentEvict.Purge()
-}
-
-// Contains is used to check if the cache contains a key
-// without updating recency or frequency.
-func (c *TwoQueueCache) Contains(key interface{}) bool {
- c.lock.RLock()
- defer c.lock.RUnlock()
- return c.frequent.Contains(key) || c.recent.Contains(key)
-}
-
-// Peek is used to inspect the cache value of a key
-// without updating recency or frequency.
-func (c *TwoQueueCache) Peek(key interface{}) (value interface{}, ok bool) {
- c.lock.RLock()
- defer c.lock.RUnlock()
- if val, ok := c.frequent.Peek(key); ok {
- return val, ok
- }
- return c.recent.Peek(key)
-}
diff --git a/vendor/github.com/hashicorp/golang-lru/LICENSE b/vendor/github.com/hashicorp/golang-lru/LICENSE
deleted file mode 100644
index be2cc4d..0000000
--- a/vendor/github.com/hashicorp/golang-lru/LICENSE
+++ /dev/null
@@ -1,362 +0,0 @@
-Mozilla Public License, version 2.0
-
-1. Definitions
-
-1.1. "Contributor"
-
- means each individual or legal entity that creates, contributes to the
- creation of, or owns Covered Software.
-
-1.2. "Contributor Version"
-
- means the combination of the Contributions of others (if any) used by a
- Contributor and that particular Contributor's Contribution.
-
-1.3. "Contribution"
-
- means Covered Software of a particular Contributor.
-
-1.4. "Covered Software"
-
- means Source Code Form to which the initial Contributor has attached the
- notice in Exhibit A, the Executable Form of such Source Code Form, and
- Modifications of such Source Code Form, in each case including portions
- thereof.
-
-1.5. "Incompatible With Secondary Licenses"
- means
-
- a. that the initial Contributor has attached the notice described in
- Exhibit B to the Covered Software; or
-
- b. that the Covered Software was made available under the terms of
- version 1.1 or earlier of the License, but not also under the terms of
- a Secondary License.
-
-1.6. "Executable Form"
-
- means any form of the work other than Source Code Form.
-
-1.7. "Larger Work"
-
- means a work that combines Covered Software with other material, in a
- separate file or files, that is not Covered Software.
-
-1.8. "License"
-
- means this document.
-
-1.9. "Licensable"
-
- means having the right to grant, to the maximum extent possible, whether
- at the time of the initial grant or subsequently, any and all of the
- rights conveyed by this License.
-
-1.10. "Modifications"
-
- means any of the following:
-
- a. any file in Source Code Form that results from an addition to,
- deletion from, or modification of the contents of Covered Software; or
-
- b. any new file in Source Code Form that contains any Covered Software.
-
-1.11. "Patent Claims" of a Contributor
-
- means any patent claim(s), including without limitation, method,
- process, and apparatus claims, in any patent Licensable by such
- Contributor that would be infringed, but for the grant of the License,
- by the making, using, selling, offering for sale, having made, import,
- or transfer of either its Contributions or its Contributor Version.
-
-1.12. "Secondary License"
-
- means either the GNU General Public License, Version 2.0, the GNU Lesser
- General Public License, Version 2.1, the GNU Affero General Public
- License, Version 3.0, or any later versions of those licenses.
-
-1.13. "Source Code Form"
-
- means the form of the work preferred for making modifications.
-
-1.14. "You" (or "Your")
-
- means an individual or a legal entity exercising rights under this
- License. For legal entities, "You" includes any entity that controls, is
- controlled by, or is under common control with You. For purposes of this
- definition, "control" means (a) the power, direct or indirect, to cause
- the direction or management of such entity, whether by contract or
- otherwise, or (b) ownership of more than fifty percent (50%) of the
- outstanding shares or beneficial ownership of such entity.
-
-
-2. License Grants and Conditions
-
-2.1. Grants
-
- Each Contributor hereby grants You a world-wide, royalty-free,
- non-exclusive license:
-
- a. under intellectual property rights (other than patent or trademark)
- Licensable by such Contributor to use, reproduce, make available,
- modify, display, perform, distribute, and otherwise exploit its
- Contributions, either on an unmodified basis, with Modifications, or
- as part of a Larger Work; and
-
- b. under Patent Claims of such Contributor to make, use, sell, offer for
- sale, have made, import, and otherwise transfer either its
- Contributions or its Contributor Version.
-
-2.2. Effective Date
-
- The licenses granted in Section 2.1 with respect to any Contribution
- become effective for each Contribution on the date the Contributor first
- distributes such Contribution.
-
-2.3. Limitations on Grant Scope
-
- The licenses granted in this Section 2 are the only rights granted under
- this License. No additional rights or licenses will be implied from the
- distribution or licensing of Covered Software under this License.
- Notwithstanding Section 2.1(b) above, no patent license is granted by a
- Contributor:
-
- a. for any code that a Contributor has removed from Covered Software; or
-
- b. for infringements caused by: (i) Your and any other third party's
- modifications of Covered Software, or (ii) the combination of its
- Contributions with other software (except as part of its Contributor
- Version); or
-
- c. under Patent Claims infringed by Covered Software in the absence of
- its Contributions.
-
- This License does not grant any rights in the trademarks, service marks,
- or logos of any Contributor (except as may be necessary to comply with
- the notice requirements in Section 3.4).
-
-2.4. Subsequent Licenses
-
- No Contributor makes additional grants as a result of Your choice to
- distribute the Covered Software under a subsequent version of this
- License (see Section 10.2) or under the terms of a Secondary License (if
- permitted under the terms of Section 3.3).
-
-2.5. Representation
-
- Each Contributor represents that the Contributor believes its
- Contributions are its original creation(s) or it has sufficient rights to
- grant the rights to its Contributions conveyed by this License.
-
-2.6. Fair Use
-
- This License is not intended to limit any rights You have under
- applicable copyright doctrines of fair use, fair dealing, or other
- equivalents.
-
-2.7. Conditions
-
- Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
- Section 2.1.
-
-
-3. Responsibilities
-
-3.1. Distribution of Source Form
-
- All distribution of Covered Software in Source Code Form, including any
- Modifications that You create or to which You contribute, must be under
- the terms of this License. You must inform recipients that the Source
- Code Form of the Covered Software is governed by the terms of this
- License, and how they can obtain a copy of this License. You may not
- attempt to alter or restrict the recipients' rights in the Source Code
- Form.
-
-3.2. Distribution of Executable Form
-
- If You distribute Covered Software in Executable Form then:
-
- a. such Covered Software must also be made available in Source Code Form,
- as described in Section 3.1, and You must inform recipients of the
- Executable Form how they can obtain a copy of such Source Code Form by
- reasonable means in a timely manner, at a charge no more than the cost
- of distribution to the recipient; and
-
- b. You may distribute such Executable Form under the terms of this
- License, or sublicense it under different terms, provided that the
- license for the Executable Form does not attempt to limit or alter the
- recipients' rights in the Source Code Form under this License.
-
-3.3. Distribution of a Larger Work
-
- You may create and distribute a Larger Work under terms of Your choice,
- provided that You also comply with the requirements of this License for
- the Covered Software. If the Larger Work is a combination of Covered
- Software with a work governed by one or more Secondary Licenses, and the
- Covered Software is not Incompatible With Secondary Licenses, this
- License permits You to additionally distribute such Covered Software
- under the terms of such Secondary License(s), so that the recipient of
- the Larger Work may, at their option, further distribute the Covered
- Software under the terms of either this License or such Secondary
- License(s).
-
-3.4. Notices
-
- You may not remove or alter the substance of any license notices
- (including copyright notices, patent notices, disclaimers of warranty, or
- limitations of liability) contained within the Source Code Form of the
- Covered Software, except that You may alter any license notices to the
- extent required to remedy known factual inaccuracies.
-
-3.5. Application of Additional Terms
-
- You may choose to offer, and to charge a fee for, warranty, support,
- indemnity or liability obligations to one or more recipients of Covered
- Software. However, You may do so only on Your own behalf, and not on
- behalf of any Contributor. You must make it absolutely clear that any
- such warranty, support, indemnity, or liability obligation is offered by
- You alone, and You hereby agree to indemnify every Contributor for any
- liability incurred by such Contributor as a result of warranty, support,
- indemnity or liability terms You offer. You may include additional
- disclaimers of warranty and limitations of liability specific to any
- jurisdiction.
-
-4. Inability to Comply Due to Statute or Regulation
-
- If it is impossible for You to comply with any of the terms of this License
- with respect to some or all of the Covered Software due to statute,
- judicial order, or regulation then You must: (a) comply with the terms of
- this License to the maximum extent possible; and (b) describe the
- limitations and the code they affect. Such description must be placed in a
- text file included with all distributions of the Covered Software under
- this License. Except to the extent prohibited by statute or regulation,
- such description must be sufficiently detailed for a recipient of ordinary
- skill to be able to understand it.
-
-5. Termination
-
-5.1. The rights granted under this License will terminate automatically if You
- fail to comply with any of its terms. However, if You become compliant,
- then the rights granted under this License from a particular Contributor
- are reinstated (a) provisionally, unless and until such Contributor
- explicitly and finally terminates Your grants, and (b) on an ongoing
- basis, if such Contributor fails to notify You of the non-compliance by
- some reasonable means prior to 60 days after You have come back into
- compliance. Moreover, Your grants from a particular Contributor are
- reinstated on an ongoing basis if such Contributor notifies You of the
- non-compliance by some reasonable means, this is the first time You have
- received notice of non-compliance with this License from such
- Contributor, and You become compliant prior to 30 days after Your receipt
- of the notice.
-
-5.2. If You initiate litigation against any entity by asserting a patent
- infringement claim (excluding declaratory judgment actions,
- counter-claims, and cross-claims) alleging that a Contributor Version
- directly or indirectly infringes any patent, then the rights granted to
- You by any and all Contributors for the Covered Software under Section
- 2.1 of this License shall terminate.
-
-5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
- license agreements (excluding distributors and resellers) which have been
- validly granted by You or Your distributors under this License prior to
- termination shall survive termination.
-
-6. Disclaimer of Warranty
-
- Covered Software is provided under this License on an "as is" basis,
- without warranty of any kind, either expressed, implied, or statutory,
- including, without limitation, warranties that the Covered Software is free
- of defects, merchantable, fit for a particular purpose or non-infringing.
- The entire risk as to the quality and performance of the Covered Software
- is with You. Should any Covered Software prove defective in any respect,
- You (not any Contributor) assume the cost of any necessary servicing,
- repair, or correction. This disclaimer of warranty constitutes an essential
- part of this License. No use of any Covered Software is authorized under
- this License except under this disclaimer.
-
-7. Limitation of Liability
-
- Under no circumstances and under no legal theory, whether tort (including
- negligence), contract, or otherwise, shall any Contributor, or anyone who
- distributes Covered Software as permitted above, be liable to You for any
- direct, indirect, special, incidental, or consequential damages of any
- character including, without limitation, damages for lost profits, loss of
- goodwill, work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses, even if such party shall have been
- informed of the possibility of such damages. This limitation of liability
- shall not apply to liability for death or personal injury resulting from
- such party's negligence to the extent applicable law prohibits such
- limitation. Some jurisdictions do not allow the exclusion or limitation of
- incidental or consequential damages, so this exclusion and limitation may
- not apply to You.
-
-8. Litigation
-
- Any litigation relating to this License may be brought only in the courts
- of a jurisdiction where the defendant maintains its principal place of
- business and such litigation shall be governed by laws of that
- jurisdiction, without reference to its conflict-of-law provisions. Nothing
- in this Section shall prevent a party's ability to bring cross-claims or
- counter-claims.
-
-9. Miscellaneous
-
- This License represents the complete agreement concerning the subject
- matter hereof. If any provision of this License is held to be
- unenforceable, such provision shall be reformed only to the extent
- necessary to make it enforceable. Any law or regulation which provides that
- the language of a contract shall be construed against the drafter shall not
- be used to construe this License against a Contributor.
-
-
-10. Versions of the License
-
-10.1. New Versions
-
- Mozilla Foundation is the license steward. Except as provided in Section
- 10.3, no one other than the license steward has the right to modify or
- publish new versions of this License. Each version will be given a
- distinguishing version number.
-
-10.2. Effect of New Versions
-
- You may distribute the Covered Software under the terms of the version
- of the License under which You originally received the Covered Software,
- or under the terms of any subsequent version published by the license
- steward.
-
-10.3. Modified Versions
-
- If you create software not governed by this License, and you want to
- create a new license for such software, you may create and use a
- modified version of this License if you rename the license and remove
- any references to the name of the license steward (except to note that
- such modified license differs from this License).
-
-10.4. Distributing Source Code Form that is Incompatible With Secondary
- Licenses If You choose to distribute Source Code Form that is
- Incompatible With Secondary Licenses under the terms of this version of
- the License, the notice described in Exhibit B of this License must be
- attached.
-
-Exhibit A - Source Code Form License Notice
-
- This Source Code Form is subject to the
- terms of the Mozilla Public License, v.
- 2.0. If a copy of the MPL was not
- distributed with this file, You can
- obtain one at
- http://mozilla.org/MPL/2.0/.
-
-If it is not possible or desirable to put the notice in a particular file,
-then You may include the notice in a location (such as a LICENSE file in a
-relevant directory) where a recipient would be likely to look for such a
-notice.
-
-You may add additional accurate notices of copyright ownership.
-
-Exhibit B - "Incompatible With Secondary Licenses" Notice
-
- This Source Code Form is "Incompatible
- With Secondary Licenses", as defined by
- the Mozilla Public License, v. 2.0.
diff --git a/vendor/github.com/hashicorp/golang-lru/README.md b/vendor/github.com/hashicorp/golang-lru/README.md
deleted file mode 100644
index 33e58cf..0000000
--- a/vendor/github.com/hashicorp/golang-lru/README.md
+++ /dev/null
@@ -1,25 +0,0 @@
-golang-lru
-==========
-
-This provides the `lru` package which implements a fixed-size
-thread safe LRU cache. It is based on the cache in Groupcache.
-
-Documentation
-=============
-
-Full docs are available on [Godoc](http://godoc.org/github.com/hashicorp/golang-lru)
-
-Example
-=======
-
-Using the LRU is very simple:
-
-```go
-l, _ := New(128)
-for i := 0; i < 256; i++ {
- l.Add(i, nil)
-}
-if l.Len() != 128 {
- panic(fmt.Sprintf("bad len: %v", l.Len()))
-}
-```
diff --git a/vendor/github.com/hashicorp/golang-lru/arc.go b/vendor/github.com/hashicorp/golang-lru/arc.go
deleted file mode 100644
index 555225a..0000000
--- a/vendor/github.com/hashicorp/golang-lru/arc.go
+++ /dev/null
@@ -1,257 +0,0 @@
-package lru
-
-import (
- "sync"
-
- "github.com/hashicorp/golang-lru/simplelru"
-)
-
-// ARCCache is a thread-safe fixed size Adaptive Replacement Cache (ARC).
-// ARC is an enhancement over the standard LRU cache in that tracks both
-// frequency and recency of use. This avoids a burst in access to new
-// entries from evicting the frequently used older entries. It adds some
-// additional tracking overhead to a standard LRU cache, computationally
-// it is roughly 2x the cost, and the extra memory overhead is linear
-// with the size of the cache. ARC has been patented by IBM, but is
-// similar to the TwoQueueCache (2Q) which requires setting parameters.
-type ARCCache struct {
- size int // Size is the total capacity of the cache
- p int // P is the dynamic preference towards T1 or T2
-
- t1 simplelru.LRUCache // T1 is the LRU for recently accessed items
- b1 simplelru.LRUCache // B1 is the LRU for evictions from t1
-
- t2 simplelru.LRUCache // T2 is the LRU for frequently accessed items
- b2 simplelru.LRUCache // B2 is the LRU for evictions from t2
-
- lock sync.RWMutex
-}
-
-// NewARC creates an ARC of the given size
-func NewARC(size int) (*ARCCache, error) {
- // Create the sub LRUs
- b1, err := simplelru.NewLRU(size, nil)
- if err != nil {
- return nil, err
- }
- b2, err := simplelru.NewLRU(size, nil)
- if err != nil {
- return nil, err
- }
- t1, err := simplelru.NewLRU(size, nil)
- if err != nil {
- return nil, err
- }
- t2, err := simplelru.NewLRU(size, nil)
- if err != nil {
- return nil, err
- }
-
- // Initialize the ARC
- c := &ARCCache{
- size: size,
- p: 0,
- t1: t1,
- b1: b1,
- t2: t2,
- b2: b2,
- }
- return c, nil
-}
-
-// Get looks up a key's value from the cache.
-func (c *ARCCache) Get(key interface{}) (value interface{}, ok bool) {
- c.lock.Lock()
- defer c.lock.Unlock()
-
- // If the value is contained in T1 (recent), then
- // promote it to T2 (frequent)
- if val, ok := c.t1.Peek(key); ok {
- c.t1.Remove(key)
- c.t2.Add(key, val)
- return val, ok
- }
-
- // Check if the value is contained in T2 (frequent)
- if val, ok := c.t2.Get(key); ok {
- return val, ok
- }
-
- // No hit
- return nil, false
-}
-
-// Add adds a value to the cache.
-func (c *ARCCache) Add(key, value interface{}) {
- c.lock.Lock()
- defer c.lock.Unlock()
-
- // Check if the value is contained in T1 (recent), and potentially
- // promote it to frequent T2
- if c.t1.Contains(key) {
- c.t1.Remove(key)
- c.t2.Add(key, value)
- return
- }
-
- // Check if the value is already in T2 (frequent) and update it
- if c.t2.Contains(key) {
- c.t2.Add(key, value)
- return
- }
-
- // Check if this value was recently evicted as part of the
- // recently used list
- if c.b1.Contains(key) {
- // T1 set is too small, increase P appropriately
- delta := 1
- b1Len := c.b1.Len()
- b2Len := c.b2.Len()
- if b2Len > b1Len {
- delta = b2Len / b1Len
- }
- if c.p+delta >= c.size {
- c.p = c.size
- } else {
- c.p += delta
- }
-
- // Potentially need to make room in the cache
- if c.t1.Len()+c.t2.Len() >= c.size {
- c.replace(false)
- }
-
- // Remove from B1
- c.b1.Remove(key)
-
- // Add the key to the frequently used list
- c.t2.Add(key, value)
- return
- }
-
- // Check if this value was recently evicted as part of the
- // frequently used list
- if c.b2.Contains(key) {
- // T2 set is too small, decrease P appropriately
- delta := 1
- b1Len := c.b1.Len()
- b2Len := c.b2.Len()
- if b1Len > b2Len {
- delta = b1Len / b2Len
- }
- if delta >= c.p {
- c.p = 0
- } else {
- c.p -= delta
- }
-
- // Potentially need to make room in the cache
- if c.t1.Len()+c.t2.Len() >= c.size {
- c.replace(true)
- }
-
- // Remove from B2
- c.b2.Remove(key)
-
- // Add the key to the frequently used list
- c.t2.Add(key, value)
- return
- }
-
- // Potentially need to make room in the cache
- if c.t1.Len()+c.t2.Len() >= c.size {
- c.replace(false)
- }
-
- // Keep the size of the ghost buffers trim
- if c.b1.Len() > c.size-c.p {
- c.b1.RemoveOldest()
- }
- if c.b2.Len() > c.p {
- c.b2.RemoveOldest()
- }
-
- // Add to the recently seen list
- c.t1.Add(key, value)
- return
-}
-
-// replace is used to adaptively evict from either T1 or T2
-// based on the current learned value of P
-func (c *ARCCache) replace(b2ContainsKey bool) {
- t1Len := c.t1.Len()
- if t1Len > 0 && (t1Len > c.p || (t1Len == c.p && b2ContainsKey)) {
- k, _, ok := c.t1.RemoveOldest()
- if ok {
- c.b1.Add(k, nil)
- }
- } else {
- k, _, ok := c.t2.RemoveOldest()
- if ok {
- c.b2.Add(k, nil)
- }
- }
-}
-
-// Len returns the number of cached entries
-func (c *ARCCache) Len() int {
- c.lock.RLock()
- defer c.lock.RUnlock()
- return c.t1.Len() + c.t2.Len()
-}
-
-// Keys returns all the cached keys
-func (c *ARCCache) Keys() []interface{} {
- c.lock.RLock()
- defer c.lock.RUnlock()
- k1 := c.t1.Keys()
- k2 := c.t2.Keys()
- return append(k1, k2...)
-}
-
-// Remove is used to purge a key from the cache
-func (c *ARCCache) Remove(key interface{}) {
- c.lock.Lock()
- defer c.lock.Unlock()
- if c.t1.Remove(key) {
- return
- }
- if c.t2.Remove(key) {
- return
- }
- if c.b1.Remove(key) {
- return
- }
- if c.b2.Remove(key) {
- return
- }
-}
-
-// Purge is used to clear the cache
-func (c *ARCCache) Purge() {
- c.lock.Lock()
- defer c.lock.Unlock()
- c.t1.Purge()
- c.t2.Purge()
- c.b1.Purge()
- c.b2.Purge()
-}
-
-// Contains is used to check if the cache contains a key
-// without updating recency or frequency.
-func (c *ARCCache) Contains(key interface{}) bool {
- c.lock.RLock()
- defer c.lock.RUnlock()
- return c.t1.Contains(key) || c.t2.Contains(key)
-}
-
-// Peek is used to inspect the cache value of a key
-// without updating recency or frequency.
-func (c *ARCCache) Peek(key interface{}) (value interface{}, ok bool) {
- c.lock.RLock()
- defer c.lock.RUnlock()
- if val, ok := c.t1.Peek(key); ok {
- return val, ok
- }
- return c.t2.Peek(key)
-}
diff --git a/vendor/github.com/hashicorp/golang-lru/doc.go b/vendor/github.com/hashicorp/golang-lru/doc.go
deleted file mode 100644
index 2547df9..0000000
--- a/vendor/github.com/hashicorp/golang-lru/doc.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// Package lru provides three different LRU caches of varying sophistication.
-//
-// Cache is a simple LRU cache. It is based on the
-// LRU implementation in groupcache:
-// https://github.com/golang/groupcache/tree/master/lru
-//
-// TwoQueueCache tracks frequently used and recently used entries separately.
-// This avoids a burst of accesses from taking out frequently used entries,
-// at the cost of about 2x computational overhead and some extra bookkeeping.
-//
-// ARCCache is an adaptive replacement cache. It tracks recent evictions as
-// well as recent usage in both the frequent and recent caches. Its
-// computational overhead is comparable to TwoQueueCache, but the memory
-// overhead is linear with the size of the cache.
-//
-// ARC has been patented by IBM, so do not use it if that is problematic for
-// your program.
-//
-// All caches in this package take locks while operating, and are therefore
-// thread-safe for consumers.
-package lru
diff --git a/vendor/github.com/hashicorp/golang-lru/go.mod b/vendor/github.com/hashicorp/golang-lru/go.mod
deleted file mode 100644
index 824cb97..0000000
--- a/vendor/github.com/hashicorp/golang-lru/go.mod
+++ /dev/null
@@ -1 +0,0 @@
-module github.com/hashicorp/golang-lru
diff --git a/vendor/github.com/hashicorp/golang-lru/lru.go b/vendor/github.com/hashicorp/golang-lru/lru.go
deleted file mode 100644
index c8d9b0a..0000000
--- a/vendor/github.com/hashicorp/golang-lru/lru.go
+++ /dev/null
@@ -1,110 +0,0 @@
-package lru
-
-import (
- "sync"
-
- "github.com/hashicorp/golang-lru/simplelru"
-)
-
-// Cache is a thread-safe fixed size LRU cache.
-type Cache struct {
- lru simplelru.LRUCache
- lock sync.RWMutex
-}
-
-// New creates an LRU of the given size.
-func New(size int) (*Cache, error) {
- return NewWithEvict(size, nil)
-}
-
-// NewWithEvict constructs a fixed size cache with the given eviction
-// callback.
-func NewWithEvict(size int, onEvicted func(key interface{}, value interface{})) (*Cache, error) {
- lru, err := simplelru.NewLRU(size, simplelru.EvictCallback(onEvicted))
- if err != nil {
- return nil, err
- }
- c := &Cache{
- lru: lru,
- }
- return c, nil
-}
-
-// Purge is used to completely clear the cache.
-func (c *Cache) Purge() {
- c.lock.Lock()
- c.lru.Purge()
- c.lock.Unlock()
-}
-
-// Add adds a value to the cache. Returns true if an eviction occurred.
-func (c *Cache) Add(key, value interface{}) (evicted bool) {
- c.lock.Lock()
- defer c.lock.Unlock()
- return c.lru.Add(key, value)
-}
-
-// Get looks up a key's value from the cache.
-func (c *Cache) Get(key interface{}) (value interface{}, ok bool) {
- c.lock.Lock()
- defer c.lock.Unlock()
- return c.lru.Get(key)
-}
-
-// Contains checks if a key is in the cache, without updating the
-// recent-ness or deleting it for being stale.
-func (c *Cache) Contains(key interface{}) bool {
- c.lock.RLock()
- defer c.lock.RUnlock()
- return c.lru.Contains(key)
-}
-
-// Peek returns the key value (or undefined if not found) without updating
-// the "recently used"-ness of the key.
-func (c *Cache) Peek(key interface{}) (value interface{}, ok bool) {
- c.lock.RLock()
- defer c.lock.RUnlock()
- return c.lru.Peek(key)
-}
-
-// ContainsOrAdd checks if a key is in the cache without updating the
-// recent-ness or deleting it for being stale, and if not, adds the value.
-// Returns whether found and whether an eviction occurred.
-func (c *Cache) ContainsOrAdd(key, value interface{}) (ok, evicted bool) {
- c.lock.Lock()
- defer c.lock.Unlock()
-
- if c.lru.Contains(key) {
- return true, false
- }
- evicted = c.lru.Add(key, value)
- return false, evicted
-}
-
-// Remove removes the provided key from the cache.
-func (c *Cache) Remove(key interface{}) {
- c.lock.Lock()
- c.lru.Remove(key)
- c.lock.Unlock()
-}
-
-// RemoveOldest removes the oldest item from the cache.
-func (c *Cache) RemoveOldest() {
- c.lock.Lock()
- c.lru.RemoveOldest()
- c.lock.Unlock()
-}
-
-// Keys returns a slice of the keys in the cache, from oldest to newest.
-func (c *Cache) Keys() []interface{} {
- c.lock.RLock()
- defer c.lock.RUnlock()
- return c.lru.Keys()
-}
-
-// Len returns the number of items in the cache.
-func (c *Cache) Len() int {
- c.lock.RLock()
- defer c.lock.RUnlock()
- return c.lru.Len()
-}
diff --git a/vendor/github.com/hashicorp/golang-lru/simplelru/lru.go b/vendor/github.com/hashicorp/golang-lru/simplelru/lru.go
deleted file mode 100644
index 5673773..0000000
--- a/vendor/github.com/hashicorp/golang-lru/simplelru/lru.go
+++ /dev/null
@@ -1,161 +0,0 @@
-package simplelru
-
-import (
- "container/list"
- "errors"
-)
-
-// EvictCallback is used to get a callback when a cache entry is evicted
-type EvictCallback func(key interface{}, value interface{})
-
-// LRU implements a non-thread safe fixed size LRU cache
-type LRU struct {
- size int
- evictList *list.List
- items map[interface{}]*list.Element
- onEvict EvictCallback
-}
-
-// entry is used to hold a value in the evictList
-type entry struct {
- key interface{}
- value interface{}
-}
-
-// NewLRU constructs an LRU of the given size
-func NewLRU(size int, onEvict EvictCallback) (*LRU, error) {
- if size <= 0 {
- return nil, errors.New("Must provide a positive size")
- }
- c := &LRU{
- size: size,
- evictList: list.New(),
- items: make(map[interface{}]*list.Element),
- onEvict: onEvict,
- }
- return c, nil
-}
-
-// Purge is used to completely clear the cache.
-func (c *LRU) Purge() {
- for k, v := range c.items {
- if c.onEvict != nil {
- c.onEvict(k, v.Value.(*entry).value)
- }
- delete(c.items, k)
- }
- c.evictList.Init()
-}
-
-// Add adds a value to the cache. Returns true if an eviction occurred.
-func (c *LRU) Add(key, value interface{}) (evicted bool) {
- // Check for existing item
- if ent, ok := c.items[key]; ok {
- c.evictList.MoveToFront(ent)
- ent.Value.(*entry).value = value
- return false
- }
-
- // Add new item
- ent := &entry{key, value}
- entry := c.evictList.PushFront(ent)
- c.items[key] = entry
-
- evict := c.evictList.Len() > c.size
- // Verify size not exceeded
- if evict {
- c.removeOldest()
- }
- return evict
-}
-
-// Get looks up a key's value from the cache.
-func (c *LRU) Get(key interface{}) (value interface{}, ok bool) {
- if ent, ok := c.items[key]; ok {
- c.evictList.MoveToFront(ent)
- return ent.Value.(*entry).value, true
- }
- return
-}
-
-// Contains checks if a key is in the cache, without updating the recent-ness
-// or deleting it for being stale.
-func (c *LRU) Contains(key interface{}) (ok bool) {
- _, ok = c.items[key]
- return ok
-}
-
-// Peek returns the key value (or undefined if not found) without updating
-// the "recently used"-ness of the key.
-func (c *LRU) Peek(key interface{}) (value interface{}, ok bool) {
- var ent *list.Element
- if ent, ok = c.items[key]; ok {
- return ent.Value.(*entry).value, true
- }
- return nil, ok
-}
-
-// Remove removes the provided key from the cache, returning if the
-// key was contained.
-func (c *LRU) Remove(key interface{}) (present bool) {
- if ent, ok := c.items[key]; ok {
- c.removeElement(ent)
- return true
- }
- return false
-}
-
-// RemoveOldest removes the oldest item from the cache.
-func (c *LRU) RemoveOldest() (key interface{}, value interface{}, ok bool) {
- ent := c.evictList.Back()
- if ent != nil {
- c.removeElement(ent)
- kv := ent.Value.(*entry)
- return kv.key, kv.value, true
- }
- return nil, nil, false
-}
-
-// GetOldest returns the oldest entry
-func (c *LRU) GetOldest() (key interface{}, value interface{}, ok bool) {
- ent := c.evictList.Back()
- if ent != nil {
- kv := ent.Value.(*entry)
- return kv.key, kv.value, true
- }
- return nil, nil, false
-}
-
-// Keys returns a slice of the keys in the cache, from oldest to newest.
-func (c *LRU) Keys() []interface{} {
- keys := make([]interface{}, len(c.items))
- i := 0
- for ent := c.evictList.Back(); ent != nil; ent = ent.Prev() {
- keys[i] = ent.Value.(*entry).key
- i++
- }
- return keys
-}
-
-// Len returns the number of items in the cache.
-func (c *LRU) Len() int {
- return c.evictList.Len()
-}
-
-// removeOldest removes the oldest item from the cache.
-func (c *LRU) removeOldest() {
- ent := c.evictList.Back()
- if ent != nil {
- c.removeElement(ent)
- }
-}
-
-// removeElement is used to remove a given list element from the cache
-func (c *LRU) removeElement(e *list.Element) {
- c.evictList.Remove(e)
- kv := e.Value.(*entry)
- delete(c.items, kv.key)
- if c.onEvict != nil {
- c.onEvict(kv.key, kv.value)
- }
-}
diff --git a/vendor/github.com/hashicorp/golang-lru/simplelru/lru_interface.go b/vendor/github.com/hashicorp/golang-lru/simplelru/lru_interface.go
deleted file mode 100644
index 74c7077..0000000
--- a/vendor/github.com/hashicorp/golang-lru/simplelru/lru_interface.go
+++ /dev/null
@@ -1,36 +0,0 @@
-package simplelru
-
-// LRUCache is the interface for simple LRU cache.
-type LRUCache interface {
- // Adds a value to the cache, returns true if an eviction occurred and
- // updates the "recently used"-ness of the key.
- Add(key, value interface{}) bool
-
- // Returns key's value from the cache and
- // updates the "recently used"-ness of the key. #value, isFound
- Get(key interface{}) (value interface{}, ok bool)
-
- // Check if a key exsists in cache without updating the recent-ness.
- Contains(key interface{}) (ok bool)
-
- // Returns key's value without updating the "recently used"-ness of the key.
- Peek(key interface{}) (value interface{}, ok bool)
-
- // Removes a key from the cache.
- Remove(key interface{}) bool
-
- // Removes the oldest entry from cache.
- RemoveOldest() (interface{}, interface{}, bool)
-
- // Returns the oldest entry from the cache. #key, value, isFound
- GetOldest() (interface{}, interface{}, bool)
-
- // Returns a slice of the keys in the cache, from oldest to newest.
- Keys() []interface{}
-
- // Returns the number of items in the cache.
- Len() int
-
- // Clear all cache entries
- Purge()
-}
diff --git a/vendor/golang.org/x/image/AUTHORS b/vendor/golang.org/x/image/AUTHORS
deleted file mode 100644
index 15167cd..0000000
--- a/vendor/golang.org/x/image/AUTHORS
+++ /dev/null
@@ -1,3 +0,0 @@
-# This source code refers to The Go Authors for copyright purposes.
-# The master list of authors is in the main Go distribution,
-# visible at http://tip.golang.org/AUTHORS.
diff --git a/vendor/golang.org/x/image/CONTRIBUTORS b/vendor/golang.org/x/image/CONTRIBUTORS
deleted file mode 100644
index 1c4577e..0000000
--- a/vendor/golang.org/x/image/CONTRIBUTORS
+++ /dev/null
@@ -1,3 +0,0 @@
-# This source code was written by the Go contributors.
-# The master list of contributors is in the main Go distribution,
-# visible at http://tip.golang.org/CONTRIBUTORS.
diff --git a/vendor/golang.org/x/image/LICENSE b/vendor/golang.org/x/image/LICENSE
deleted file mode 100644
index 6a66aea..0000000
--- a/vendor/golang.org/x/image/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (c) 2009 The Go Authors. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
- * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/golang.org/x/image/PATENTS b/vendor/golang.org/x/image/PATENTS
deleted file mode 100644
index 7330990..0000000
--- a/vendor/golang.org/x/image/PATENTS
+++ /dev/null
@@ -1,22 +0,0 @@
-Additional IP Rights Grant (Patents)
-
-"This implementation" means the copyrightable works distributed by
-Google as part of the Go project.
-
-Google hereby grants to You a perpetual, worldwide, non-exclusive,
-no-charge, royalty-free, irrevocable (except as stated in this section)
-patent license to make, have made, use, offer to sell, sell, import,
-transfer and otherwise run, modify and propagate the contents of this
-implementation of Go, where such license applies only to those patent
-claims, both currently owned or controlled by Google and acquired in
-the future, licensable by Google that are necessarily infringed by this
-implementation of Go. This grant does not include claims that would be
-infringed only as a consequence of further modification of this
-implementation. If you or your agent or exclusive licensee institute or
-order or agree to the institution of patent litigation against any
-entity (including a cross-claim or counterclaim in a lawsuit) alleging
-that this implementation of Go or any code incorporated within this
-implementation of Go constitutes direct or contributory patent
-infringement, or inducement of patent infringement, then any patent
-rights granted to you under this License for this implementation of Go
-shall terminate as of the date such litigation is filed.
diff --git a/vendor/golang.org/x/image/bmp/reader.go b/vendor/golang.org/x/image/bmp/reader.go
deleted file mode 100644
index a0f2715..0000000
--- a/vendor/golang.org/x/image/bmp/reader.go
+++ /dev/null
@@ -1,199 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package bmp implements a BMP image decoder and encoder.
-//
-// The BMP specification is at http://www.digicamsoft.com/bmp/bmp.html.
-package bmp // import "golang.org/x/image/bmp"
-
-import (
- "errors"
- "image"
- "image/color"
- "io"
-)
-
-// ErrUnsupported means that the input BMP image uses a valid but unsupported
-// feature.
-var ErrUnsupported = errors.New("bmp: unsupported BMP image")
-
-func readUint16(b []byte) uint16 {
- return uint16(b[0]) | uint16(b[1])<<8
-}
-
-func readUint32(b []byte) uint32 {
- return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
-}
-
-// decodePaletted reads an 8 bit-per-pixel BMP image from r.
-// If topDown is false, the image rows will be read bottom-up.
-func decodePaletted(r io.Reader, c image.Config, topDown bool) (image.Image, error) {
- paletted := image.NewPaletted(image.Rect(0, 0, c.Width, c.Height), c.ColorModel.(color.Palette))
- if c.Width == 0 || c.Height == 0 {
- return paletted, nil
- }
- var tmp [4]byte
- y0, y1, yDelta := c.Height-1, -1, -1
- if topDown {
- y0, y1, yDelta = 0, c.Height, +1
- }
- for y := y0; y != y1; y += yDelta {
- p := paletted.Pix[y*paletted.Stride : y*paletted.Stride+c.Width]
- if _, err := io.ReadFull(r, p); err != nil {
- return nil, err
- }
- // Each row is 4-byte aligned.
- if c.Width%4 != 0 {
- _, err := io.ReadFull(r, tmp[:4-c.Width%4])
- if err != nil {
- return nil, err
- }
- }
- }
- return paletted, nil
-}
-
-// decodeRGB reads a 24 bit-per-pixel BMP image from r.
-// If topDown is false, the image rows will be read bottom-up.
-func decodeRGB(r io.Reader, c image.Config, topDown bool) (image.Image, error) {
- rgba := image.NewRGBA(image.Rect(0, 0, c.Width, c.Height))
- if c.Width == 0 || c.Height == 0 {
- return rgba, nil
- }
- // There are 3 bytes per pixel, and each row is 4-byte aligned.
- b := make([]byte, (3*c.Width+3)&^3)
- y0, y1, yDelta := c.Height-1, -1, -1
- if topDown {
- y0, y1, yDelta = 0, c.Height, +1
- }
- for y := y0; y != y1; y += yDelta {
- if _, err := io.ReadFull(r, b); err != nil {
- return nil, err
- }
- p := rgba.Pix[y*rgba.Stride : y*rgba.Stride+c.Width*4]
- for i, j := 0, 0; i < len(p); i, j = i+4, j+3 {
- // BMP images are stored in BGR order rather than RGB order.
- p[i+0] = b[j+2]
- p[i+1] = b[j+1]
- p[i+2] = b[j+0]
- p[i+3] = 0xFF
- }
- }
- return rgba, nil
-}
-
-// decodeNRGBA reads a 32 bit-per-pixel BMP image from r.
-// If topDown is false, the image rows will be read bottom-up.
-func decodeNRGBA(r io.Reader, c image.Config, topDown bool) (image.Image, error) {
- rgba := image.NewNRGBA(image.Rect(0, 0, c.Width, c.Height))
- if c.Width == 0 || c.Height == 0 {
- return rgba, nil
- }
- y0, y1, yDelta := c.Height-1, -1, -1
- if topDown {
- y0, y1, yDelta = 0, c.Height, +1
- }
- for y := y0; y != y1; y += yDelta {
- p := rgba.Pix[y*rgba.Stride : y*rgba.Stride+c.Width*4]
- if _, err := io.ReadFull(r, p); err != nil {
- return nil, err
- }
- for i := 0; i < len(p); i += 4 {
- // BMP images are stored in BGRA order rather than RGBA order.
- p[i+0], p[i+2] = p[i+2], p[i+0]
- }
- }
- return rgba, nil
-}
-
-// Decode reads a BMP image from r and returns it as an image.Image.
-// Limitation: The file must be 8, 24 or 32 bits per pixel.
-func Decode(r io.Reader) (image.Image, error) {
- c, bpp, topDown, err := decodeConfig(r)
- if err != nil {
- return nil, err
- }
- switch bpp {
- case 8:
- return decodePaletted(r, c, topDown)
- case 24:
- return decodeRGB(r, c, topDown)
- case 32:
- return decodeNRGBA(r, c, topDown)
- }
- panic("unreachable")
-}
-
-// DecodeConfig returns the color model and dimensions of a BMP image without
-// decoding the entire image.
-// Limitation: The file must be 8, 24 or 32 bits per pixel.
-func DecodeConfig(r io.Reader) (image.Config, error) {
- config, _, _, err := decodeConfig(r)
- return config, err
-}
-
-func decodeConfig(r io.Reader) (config image.Config, bitsPerPixel int, topDown bool, err error) {
- // We only support those BMP images that are a BITMAPFILEHEADER
- // immediately followed by a BITMAPINFOHEADER.
- const (
- fileHeaderLen = 14
- infoHeaderLen = 40
- )
- var b [1024]byte
- if _, err := io.ReadFull(r, b[:fileHeaderLen+infoHeaderLen]); err != nil {
- return image.Config{}, 0, false, err
- }
- if string(b[:2]) != "BM" {
- return image.Config{}, 0, false, errors.New("bmp: invalid format")
- }
- offset := readUint32(b[10:14])
- if readUint32(b[14:18]) != infoHeaderLen {
- return image.Config{}, 0, false, ErrUnsupported
- }
- width := int(int32(readUint32(b[18:22])))
- height := int(int32(readUint32(b[22:26])))
- if height < 0 {
- height, topDown = -height, true
- }
- if width < 0 || height < 0 {
- return image.Config{}, 0, false, ErrUnsupported
- }
- // We only support 1 plane, 8 or 24 bits per pixel and no compression.
- planes, bpp, compression := readUint16(b[26:28]), readUint16(b[28:30]), readUint32(b[30:34])
- if planes != 1 || compression != 0 {
- return image.Config{}, 0, false, ErrUnsupported
- }
- switch bpp {
- case 8:
- if offset != fileHeaderLen+infoHeaderLen+256*4 {
- return image.Config{}, 0, false, ErrUnsupported
- }
- _, err = io.ReadFull(r, b[:256*4])
- if err != nil {
- return image.Config{}, 0, false, err
- }
- pcm := make(color.Palette, 256)
- for i := range pcm {
- // BMP images are stored in BGR order rather than RGB order.
- // Every 4th byte is padding.
- pcm[i] = color.RGBA{b[4*i+2], b[4*i+1], b[4*i+0], 0xFF}
- }
- return image.Config{ColorModel: pcm, Width: width, Height: height}, 8, topDown, nil
- case 24:
- if offset != fileHeaderLen+infoHeaderLen {
- return image.Config{}, 0, false, ErrUnsupported
- }
- return image.Config{ColorModel: color.RGBAModel, Width: width, Height: height}, 24, topDown, nil
- case 32:
- if offset != fileHeaderLen+infoHeaderLen {
- return image.Config{}, 0, false, ErrUnsupported
- }
- return image.Config{ColorModel: color.RGBAModel, Width: width, Height: height}, 32, topDown, nil
- }
- return image.Config{}, 0, false, ErrUnsupported
-}
-
-func init() {
- image.RegisterFormat("bmp", "BM????\x00\x00\x00\x00", Decode, DecodeConfig)
-}
diff --git a/vendor/golang.org/x/image/bmp/writer.go b/vendor/golang.org/x/image/bmp/writer.go
deleted file mode 100644
index 6947968..0000000
--- a/vendor/golang.org/x/image/bmp/writer.go
+++ /dev/null
@@ -1,166 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package bmp
-
-import (
- "encoding/binary"
- "errors"
- "image"
- "io"
-)
-
-type header struct {
- sigBM [2]byte
- fileSize uint32
- resverved [2]uint16
- pixOffset uint32
- dibHeaderSize uint32
- width uint32
- height uint32
- colorPlane uint16
- bpp uint16
- compression uint32
- imageSize uint32
- xPixelsPerMeter uint32
- yPixelsPerMeter uint32
- colorUse uint32
- colorImportant uint32
-}
-
-func encodePaletted(w io.Writer, pix []uint8, dx, dy, stride, step int) error {
- var padding []byte
- if dx < step {
- padding = make([]byte, step-dx)
- }
- for y := dy - 1; y >= 0; y-- {
- min := y*stride + 0
- max := y*stride + dx
- if _, err := w.Write(pix[min:max]); err != nil {
- return err
- }
- if padding != nil {
- if _, err := w.Write(padding); err != nil {
- return err
- }
- }
- }
- return nil
-}
-
-func encodeRGBA(w io.Writer, pix []uint8, dx, dy, stride, step int) error {
- buf := make([]byte, step)
- for y := dy - 1; y >= 0; y-- {
- min := y*stride + 0
- max := y*stride + dx*4
- off := 0
- for i := min; i < max; i += 4 {
- buf[off+2] = pix[i+0]
- buf[off+1] = pix[i+1]
- buf[off+0] = pix[i+2]
- off += 3
- }
- if _, err := w.Write(buf); err != nil {
- return err
- }
- }
- return nil
-}
-
-func encode(w io.Writer, m image.Image, step int) error {
- b := m.Bounds()
- buf := make([]byte, step)
- for y := b.Max.Y - 1; y >= b.Min.Y; y-- {
- off := 0
- for x := b.Min.X; x < b.Max.X; x++ {
- r, g, b, _ := m.At(x, y).RGBA()
- buf[off+2] = byte(r >> 8)
- buf[off+1] = byte(g >> 8)
- buf[off+0] = byte(b >> 8)
- off += 3
- }
- if _, err := w.Write(buf); err != nil {
- return err
- }
- }
- return nil
-}
-
-// Encode writes the image m to w in BMP format.
-func Encode(w io.Writer, m image.Image) error {
- d := m.Bounds().Size()
- if d.X < 0 || d.Y < 0 {
- return errors.New("bmp: negative bounds")
- }
- h := &header{
- sigBM: [2]byte{'B', 'M'},
- fileSize: 14 + 40,
- pixOffset: 14 + 40,
- dibHeaderSize: 40,
- width: uint32(d.X),
- height: uint32(d.Y),
- colorPlane: 1,
- }
-
- var step int
- var palette []byte
- switch m := m.(type) {
- case *image.Gray:
- step = (d.X + 3) &^ 3
- palette = make([]byte, 1024)
- for i := 0; i < 256; i++ {
- palette[i*4+0] = uint8(i)
- palette[i*4+1] = uint8(i)
- palette[i*4+2] = uint8(i)
- palette[i*4+3] = 0xFF
- }
- h.imageSize = uint32(d.Y * step)
- h.fileSize += uint32(len(palette)) + h.imageSize
- h.pixOffset += uint32(len(palette))
- h.bpp = 8
-
- case *image.Paletted:
- step = (d.X + 3) &^ 3
- palette = make([]byte, 1024)
- for i := 0; i < len(m.Palette) && i < 256; i++ {
- r, g, b, _ := m.Palette[i].RGBA()
- palette[i*4+0] = uint8(b >> 8)
- palette[i*4+1] = uint8(g >> 8)
- palette[i*4+2] = uint8(r >> 8)
- palette[i*4+3] = 0xFF
- }
- h.imageSize = uint32(d.Y * step)
- h.fileSize += uint32(len(palette)) + h.imageSize
- h.pixOffset += uint32(len(palette))
- h.bpp = 8
- default:
- step = (3*d.X + 3) &^ 3
- h.imageSize = uint32(d.Y * step)
- h.fileSize += h.imageSize
- h.bpp = 24
- }
-
- if err := binary.Write(w, binary.LittleEndian, h); err != nil {
- return err
- }
- if palette != nil {
- if err := binary.Write(w, binary.LittleEndian, palette); err != nil {
- return err
- }
- }
-
- if d.X == 0 || d.Y == 0 {
- return nil
- }
-
- switch m := m.(type) {
- case *image.Gray:
- return encodePaletted(w, m.Pix, d.X, d.Y, m.Stride, step)
- case *image.Paletted:
- return encodePaletted(w, m.Pix, d.X, d.Y, m.Stride, step)
- case *image.RGBA:
- return encodeRGBA(w, m.Pix, d.X, d.Y, m.Stride, step)
- }
- return encode(w, m, step)
-}
diff --git a/vendor/golang.org/x/image/draw/draw.go b/vendor/golang.org/x/image/draw/draw.go
deleted file mode 100644
index dfaa7fc..0000000
--- a/vendor/golang.org/x/image/draw/draw.go
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package draw provides image composition functions.
-//
-// See "The Go image/draw package" for an introduction to this package:
-// http://golang.org/doc/articles/image_draw.html
-//
-// This package is a superset of and a drop-in replacement for the image/draw
-// package in the standard library.
-package draw
-
-// This file, and the go1_*.go files, just contains the API exported by the
-// image/draw package in the standard library. Other files in this package
-// provide additional features.
-
-import (
- "image"
- "image/draw"
-)
-
-// Draw calls DrawMask with a nil mask.
-func Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point, op Op) {
- draw.Draw(dst, r, src, sp, draw.Op(op))
-}
-
-// DrawMask aligns r.Min in dst with sp in src and mp in mask and then
-// replaces the rectangle r in dst with the result of a Porter-Duff
-// composition. A nil mask is treated as opaque.
-func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op Op) {
- draw.DrawMask(dst, r, src, sp, mask, mp, draw.Op(op))
-}
-
-// FloydSteinberg is a Drawer that is the Src Op with Floyd-Steinberg error
-// diffusion.
-var FloydSteinberg Drawer = floydSteinberg{}
-
-type floydSteinberg struct{}
-
-func (floydSteinberg) Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point) {
- draw.FloydSteinberg.Draw(dst, r, src, sp)
-}
diff --git a/vendor/golang.org/x/image/draw/gen.go b/vendor/golang.org/x/image/draw/gen.go
deleted file mode 100644
index 822bb6a..0000000
--- a/vendor/golang.org/x/image/draw/gen.go
+++ /dev/null
@@ -1,1404 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore
-
-package main
-
-import (
- "bytes"
- "flag"
- "fmt"
- "go/format"
- "io/ioutil"
- "log"
- "os"
- "strings"
-)
-
-var debug = flag.Bool("debug", false, "")
-
-func main() {
- flag.Parse()
-
- w := new(bytes.Buffer)
- w.WriteString("// generated by \"go run gen.go\". DO NOT EDIT.\n\n" +
- "package draw\n\nimport (\n" +
- "\"image\"\n" +
- "\"image/color\"\n" +
- "\"math\"\n" +
- "\n" +
- "\"golang.org/x/image/math/f64\"\n" +
- ")\n")
-
- gen(w, "nnInterpolator", codeNNScaleLeaf, codeNNTransformLeaf)
- gen(w, "ablInterpolator", codeABLScaleLeaf, codeABLTransformLeaf)
- genKernel(w)
-
- if *debug {
- os.Stdout.Write(w.Bytes())
- return
- }
- out, err := format.Source(w.Bytes())
- if err != nil {
- log.Fatal(err)
- }
- if err := ioutil.WriteFile("impl.go", out, 0660); err != nil {
- log.Fatal(err)
- }
-}
-
-var (
- // dsTypes are the (dst image type, src image type) pairs to generate
- // scale_DType_SType implementations for. The last element in the slice
- // should be the fallback pair ("Image", "image.Image").
- //
- // TODO: add *image.CMYK src type after Go 1.5 is released.
- // An *image.CMYK is also alwaysOpaque.
- dsTypes = []struct{ dType, sType string }{
- {"*image.RGBA", "*image.Gray"},
- {"*image.RGBA", "*image.NRGBA"},
- {"*image.RGBA", "*image.RGBA"},
- {"*image.RGBA", "*image.YCbCr"},
- {"*image.RGBA", "image.Image"},
- {"Image", "image.Image"},
- }
- dTypes, sTypes []string
- sTypesForDType = map[string][]string{}
- subsampleRatios = []string{
- "444",
- "422",
- "420",
- "440",
- }
- ops = []string{"Over", "Src"}
- // alwaysOpaque are those image.Image implementations that are always
- // opaque. For these types, Over is equivalent to the faster Src, in the
- // absence of a source mask.
- alwaysOpaque = map[string]bool{
- "*image.Gray": true,
- "*image.YCbCr": true,
- }
-)
-
-func init() {
- dTypesSeen := map[string]bool{}
- sTypesSeen := map[string]bool{}
- for _, t := range dsTypes {
- if !sTypesSeen[t.sType] {
- sTypesSeen[t.sType] = true
- sTypes = append(sTypes, t.sType)
- }
- if !dTypesSeen[t.dType] {
- dTypesSeen[t.dType] = true
- dTypes = append(dTypes, t.dType)
- }
- sTypesForDType[t.dType] = append(sTypesForDType[t.dType], t.sType)
- }
- sTypesForDType["anyDType"] = sTypes
-}
-
-type data struct {
- dType string
- sType string
- sratio string
- receiver string
- op string
-}
-
-func gen(w *bytes.Buffer, receiver string, codes ...string) {
- expn(w, codeRoot, &data{receiver: receiver})
- for _, code := range codes {
- for _, t := range dsTypes {
- for _, op := range ops {
- if op == "Over" && alwaysOpaque[t.sType] {
- continue
- }
- expn(w, code, &data{
- dType: t.dType,
- sType: t.sType,
- receiver: receiver,
- op: op,
- })
- }
- }
- }
-}
-
-func genKernel(w *bytes.Buffer) {
- expn(w, codeKernelRoot, &data{})
- for _, sType := range sTypes {
- expn(w, codeKernelScaleLeafX, &data{
- sType: sType,
- })
- }
- for _, dType := range dTypes {
- for _, op := range ops {
- expn(w, codeKernelScaleLeafY, &data{
- dType: dType,
- op: op,
- })
- }
- }
- for _, t := range dsTypes {
- for _, op := range ops {
- if op == "Over" && alwaysOpaque[t.sType] {
- continue
- }
- expn(w, codeKernelTransformLeaf, &data{
- dType: t.dType,
- sType: t.sType,
- op: op,
- })
- }
- }
-}
-
-func expn(w *bytes.Buffer, code string, d *data) {
- if d.sType == "*image.YCbCr" && d.sratio == "" {
- for _, sratio := range subsampleRatios {
- e := *d
- e.sratio = sratio
- expn(w, code, &e)
- }
- return
- }
-
- for _, line := range strings.Split(code, "\n") {
- line = expnLine(line, d)
- if line == ";" {
- continue
- }
- fmt.Fprintln(w, line)
- }
-}
-
-func expnLine(line string, d *data) string {
- for {
- i := strings.IndexByte(line, '$')
- if i < 0 {
- break
- }
- prefix, s := line[:i], line[i+1:]
-
- i = len(s)
- for j, c := range s {
- if !('A' <= c && c <= 'Z' || 'a' <= c && c <= 'z') {
- i = j
- break
- }
- }
- dollar, suffix := s[:i], s[i:]
-
- e := expnDollar(prefix, dollar, suffix, d)
- if e == "" {
- log.Fatalf("couldn't expand %q", line)
- }
- line = e
- }
- return line
-}
-
-// expnDollar expands a "$foo" fragment in a line of generated code. It returns
-// the empty string if there was a problem. It returns ";" if the generated
-// code is a no-op.
-func expnDollar(prefix, dollar, suffix string, d *data) string {
- switch dollar {
- case "dType":
- return prefix + d.dType + suffix
- case "dTypeRN":
- return prefix + relName(d.dType) + suffix
- case "sratio":
- return prefix + d.sratio + suffix
- case "sType":
- return prefix + d.sType + suffix
- case "sTypeRN":
- return prefix + relName(d.sType) + suffix
- case "receiver":
- return prefix + d.receiver + suffix
- case "op":
- return prefix + d.op + suffix
-
- case "switch":
- return expnSwitch("", "", true, suffix)
- case "switchD":
- return expnSwitch("", "", false, suffix)
- case "switchS":
- return expnSwitch("", "anyDType", false, suffix)
-
- case "preOuter":
- switch d.dType {
- default:
- return ";"
- case "Image":
- s := ""
- if d.sType == "image.Image" {
- s = "srcMask, smp := opts.SrcMask, opts.SrcMaskP\n"
- }
- return s +
- "dstMask, dmp := opts.DstMask, opts.DstMaskP\n" +
- "dstColorRGBA64 := &color.RGBA64{}\n" +
- "dstColor := color.Color(dstColorRGBA64)"
- }
-
- case "preInner":
- switch d.dType {
- default:
- return ";"
- case "*image.RGBA":
- return "d := " + pixOffset("dst", "dr.Min.X+adr.Min.X", "dr.Min.Y+int(dy)", "*4", "*dst.Stride")
- }
-
- case "preKernelOuter":
- switch d.sType {
- default:
- return ";"
- case "image.Image":
- return "srcMask, smp := opts.SrcMask, opts.SrcMaskP"
- }
-
- case "preKernelInner":
- switch d.dType {
- default:
- return ";"
- case "*image.RGBA":
- return "d := " + pixOffset("dst", "dr.Min.X+int(dx)", "dr.Min.Y+adr.Min.Y", "*4", "*dst.Stride")
- }
-
- case "blend":
- args, _ := splitArgs(suffix)
- if len(args) != 4 {
- return ""
- }
- switch d.sType {
- default:
- return argf(args, ""+
- "$3r = $0*$1r + $2*$3r\n"+
- "$3g = $0*$1g + $2*$3g\n"+
- "$3b = $0*$1b + $2*$3b\n"+
- "$3a = $0*$1a + $2*$3a",
- )
- case "*image.Gray":
- return argf(args, ""+
- "$3r = $0*$1r + $2*$3r",
- )
- case "*image.YCbCr":
- return argf(args, ""+
- "$3r = $0*$1r + $2*$3r\n"+
- "$3g = $0*$1g + $2*$3g\n"+
- "$3b = $0*$1b + $2*$3b",
- )
- }
-
- case "clampToAlpha":
- if alwaysOpaque[d.sType] {
- return ";"
- }
- // Go uses alpha-premultiplied color. The naive computation can lead to
- // invalid colors, e.g. red > alpha, when some weights are negative.
- return `
- if pr > pa {
- pr = pa
- }
- if pg > pa {
- pg = pa
- }
- if pb > pa {
- pb = pa
- }
- `
-
- case "convFtou":
- args, _ := splitArgs(suffix)
- if len(args) != 2 {
- return ""
- }
-
- switch d.sType {
- default:
- return argf(args, ""+
- "$0r := uint32($1r)\n"+
- "$0g := uint32($1g)\n"+
- "$0b := uint32($1b)\n"+
- "$0a := uint32($1a)",
- )
- case "*image.Gray":
- return argf(args, ""+
- "$0r := uint32($1r)",
- )
- case "*image.YCbCr":
- return argf(args, ""+
- "$0r := uint32($1r)\n"+
- "$0g := uint32($1g)\n"+
- "$0b := uint32($1b)",
- )
- }
-
- case "outputu":
- args, _ := splitArgs(suffix)
- if len(args) != 3 {
- return ""
- }
-
- switch d.op {
- case "Over":
- switch d.dType {
- default:
- log.Fatalf("bad dType %q", d.dType)
- case "Image":
- return argf(args, ""+
- "qr, qg, qb, qa := dst.At($0, $1).RGBA()\n"+
- "if dstMask != nil {\n"+
- " _, _, _, ma := dstMask.At(dmp.X + $0, dmp.Y + $1).RGBA()\n"+
- " $2r = $2r * ma / 0xffff\n"+
- " $2g = $2g * ma / 0xffff\n"+
- " $2b = $2b * ma / 0xffff\n"+
- " $2a = $2a * ma / 0xffff\n"+
- "}\n"+
- "$2a1 := 0xffff - $2a\n"+
- "dstColorRGBA64.R = uint16(qr*$2a1/0xffff + $2r)\n"+
- "dstColorRGBA64.G = uint16(qg*$2a1/0xffff + $2g)\n"+
- "dstColorRGBA64.B = uint16(qb*$2a1/0xffff + $2b)\n"+
- "dstColorRGBA64.A = uint16(qa*$2a1/0xffff + $2a)\n"+
- "dst.Set($0, $1, dstColor)",
- )
- case "*image.RGBA":
- return argf(args, ""+
- "$2a1 := (0xffff - $2a) * 0x101\n"+
- "dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*$2a1/0xffff + $2r) >> 8)\n"+
- "dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*$2a1/0xffff + $2g) >> 8)\n"+
- "dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*$2a1/0xffff + $2b) >> 8)\n"+
- "dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*$2a1/0xffff + $2a) >> 8)",
- )
- }
-
- case "Src":
- switch d.dType {
- default:
- log.Fatalf("bad dType %q", d.dType)
- case "Image":
- return argf(args, ""+
- "if dstMask != nil {\n"+
- " qr, qg, qb, qa := dst.At($0, $1).RGBA()\n"+
- " _, _, _, ma := dstMask.At(dmp.X + $0, dmp.Y + $1).RGBA()\n"+
- " pr = pr * ma / 0xffff\n"+
- " pg = pg * ma / 0xffff\n"+
- " pb = pb * ma / 0xffff\n"+
- " pa = pa * ma / 0xffff\n"+
- " $2a1 := 0xffff - ma\n"+ // Note that this is ma, not $2a.
- " dstColorRGBA64.R = uint16(qr*$2a1/0xffff + $2r)\n"+
- " dstColorRGBA64.G = uint16(qg*$2a1/0xffff + $2g)\n"+
- " dstColorRGBA64.B = uint16(qb*$2a1/0xffff + $2b)\n"+
- " dstColorRGBA64.A = uint16(qa*$2a1/0xffff + $2a)\n"+
- " dst.Set($0, $1, dstColor)\n"+
- "} else {\n"+
- " dstColorRGBA64.R = uint16($2r)\n"+
- " dstColorRGBA64.G = uint16($2g)\n"+
- " dstColorRGBA64.B = uint16($2b)\n"+
- " dstColorRGBA64.A = uint16($2a)\n"+
- " dst.Set($0, $1, dstColor)\n"+
- "}",
- )
- case "*image.RGBA":
- switch d.sType {
- default:
- return argf(args, ""+
- "dst.Pix[d+0] = uint8($2r >> 8)\n"+
- "dst.Pix[d+1] = uint8($2g >> 8)\n"+
- "dst.Pix[d+2] = uint8($2b >> 8)\n"+
- "dst.Pix[d+3] = uint8($2a >> 8)",
- )
- case "*image.Gray":
- return argf(args, ""+
- "out := uint8($2r >> 8)\n"+
- "dst.Pix[d+0] = out\n"+
- "dst.Pix[d+1] = out\n"+
- "dst.Pix[d+2] = out\n"+
- "dst.Pix[d+3] = 0xff",
- )
- case "*image.YCbCr":
- return argf(args, ""+
- "dst.Pix[d+0] = uint8($2r >> 8)\n"+
- "dst.Pix[d+1] = uint8($2g >> 8)\n"+
- "dst.Pix[d+2] = uint8($2b >> 8)\n"+
- "dst.Pix[d+3] = 0xff",
- )
- }
- }
- }
-
- case "outputf":
- args, _ := splitArgs(suffix)
- if len(args) != 5 {
- return ""
- }
- ret := ""
-
- switch d.op {
- case "Over":
- switch d.dType {
- default:
- log.Fatalf("bad dType %q", d.dType)
- case "Image":
- ret = argf(args, ""+
- "qr, qg, qb, qa := dst.At($0, $1).RGBA()\n"+
- "$3r0 := uint32($2($3r * $4))\n"+
- "$3g0 := uint32($2($3g * $4))\n"+
- "$3b0 := uint32($2($3b * $4))\n"+
- "$3a0 := uint32($2($3a * $4))\n"+
- "if dstMask != nil {\n"+
- " _, _, _, ma := dstMask.At(dmp.X + $0, dmp.Y + $1).RGBA()\n"+
- " $3r0 = $3r0 * ma / 0xffff\n"+
- " $3g0 = $3g0 * ma / 0xffff\n"+
- " $3b0 = $3b0 * ma / 0xffff\n"+
- " $3a0 = $3a0 * ma / 0xffff\n"+
- "}\n"+
- "$3a1 := 0xffff - $3a0\n"+
- "dstColorRGBA64.R = uint16(qr*$3a1/0xffff + $3r0)\n"+
- "dstColorRGBA64.G = uint16(qg*$3a1/0xffff + $3g0)\n"+
- "dstColorRGBA64.B = uint16(qb*$3a1/0xffff + $3b0)\n"+
- "dstColorRGBA64.A = uint16(qa*$3a1/0xffff + $3a0)\n"+
- "dst.Set($0, $1, dstColor)",
- )
- case "*image.RGBA":
- ret = argf(args, ""+
- "$3r0 := uint32($2($3r * $4))\n"+
- "$3g0 := uint32($2($3g * $4))\n"+
- "$3b0 := uint32($2($3b * $4))\n"+
- "$3a0 := uint32($2($3a * $4))\n"+
- "$3a1 := (0xffff - uint32($3a0)) * 0x101\n"+
- "dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*$3a1/0xffff + $3r0) >> 8)\n"+
- "dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*$3a1/0xffff + $3g0) >> 8)\n"+
- "dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*$3a1/0xffff + $3b0) >> 8)\n"+
- "dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*$3a1/0xffff + $3a0) >> 8)",
- )
- }
-
- case "Src":
- switch d.dType {
- default:
- log.Fatalf("bad dType %q", d.dType)
- case "Image":
- ret = argf(args, ""+
- "if dstMask != nil {\n"+
- " qr, qg, qb, qa := dst.At($0, $1).RGBA()\n"+
- " _, _, _, ma := dstMask.At(dmp.X + $0, dmp.Y + $1).RGBA()\n"+
- " pr := uint32($2($3r * $4)) * ma / 0xffff\n"+
- " pg := uint32($2($3g * $4)) * ma / 0xffff\n"+
- " pb := uint32($2($3b * $4)) * ma / 0xffff\n"+
- " pa := uint32($2($3a * $4)) * ma / 0xffff\n"+
- " pa1 := 0xffff - ma\n"+ // Note that this is ma, not pa.
- " dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)\n"+
- " dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)\n"+
- " dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)\n"+
- " dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)\n"+
- " dst.Set($0, $1, dstColor)\n"+
- "} else {\n"+
- " dstColorRGBA64.R = $2($3r * $4)\n"+
- " dstColorRGBA64.G = $2($3g * $4)\n"+
- " dstColorRGBA64.B = $2($3b * $4)\n"+
- " dstColorRGBA64.A = $2($3a * $4)\n"+
- " dst.Set($0, $1, dstColor)\n"+
- "}",
- )
- case "*image.RGBA":
- switch d.sType {
- default:
- ret = argf(args, ""+
- "dst.Pix[d+0] = uint8($2($3r * $4) >> 8)\n"+
- "dst.Pix[d+1] = uint8($2($3g * $4) >> 8)\n"+
- "dst.Pix[d+2] = uint8($2($3b * $4) >> 8)\n"+
- "dst.Pix[d+3] = uint8($2($3a * $4) >> 8)",
- )
- case "*image.Gray":
- ret = argf(args, ""+
- "out := uint8($2($3r * $4) >> 8)\n"+
- "dst.Pix[d+0] = out\n"+
- "dst.Pix[d+1] = out\n"+
- "dst.Pix[d+2] = out\n"+
- "dst.Pix[d+3] = 0xff",
- )
- case "*image.YCbCr":
- ret = argf(args, ""+
- "dst.Pix[d+0] = uint8($2($3r * $4) >> 8)\n"+
- "dst.Pix[d+1] = uint8($2($3g * $4) >> 8)\n"+
- "dst.Pix[d+2] = uint8($2($3b * $4) >> 8)\n"+
- "dst.Pix[d+3] = 0xff",
- )
- }
- }
- }
-
- return strings.Replace(ret, " * 1)", ")", -1)
-
- case "srcf", "srcu":
- lhs, eqOp := splitEq(prefix)
- if lhs == "" {
- return ""
- }
- args, extra := splitArgs(suffix)
- if len(args) != 2 {
- return ""
- }
-
- tmp := ""
- if dollar == "srcf" {
- tmp = "u"
- }
-
- // TODO: there's no need to multiply by 0x101 in the switch below if
- // the next thing we're going to do is shift right by 8.
-
- buf := new(bytes.Buffer)
- switch d.sType {
- default:
- log.Fatalf("bad sType %q", d.sType)
- case "image.Image":
- fmt.Fprintf(buf, ""+
- "%sr%s, %sg%s, %sb%s, %sa%s := src.At(%s, %s).RGBA()\n",
- lhs, tmp, lhs, tmp, lhs, tmp, lhs, tmp, args[0], args[1],
- )
- if d.dType == "" || d.dType == "Image" {
- fmt.Fprintf(buf, ""+
- "if srcMask != nil {\n"+
- " _, _, _, ma := srcMask.At(smp.X+%s, smp.Y+%s).RGBA()\n"+
- " %sr%s = %sr%s * ma / 0xffff\n"+
- " %sg%s = %sg%s * ma / 0xffff\n"+
- " %sb%s = %sb%s * ma / 0xffff\n"+
- " %sa%s = %sa%s * ma / 0xffff\n"+
- "}\n",
- args[0], args[1],
- lhs, tmp, lhs, tmp,
- lhs, tmp, lhs, tmp,
- lhs, tmp, lhs, tmp,
- lhs, tmp, lhs, tmp,
- )
- }
- case "*image.Gray":
- fmt.Fprintf(buf, ""+
- "%si := %s\n"+
- "%sr%s := uint32(src.Pix[%si]) * 0x101\n",
- lhs, pixOffset("src", args[0], args[1], "", "*src.Stride"),
- lhs, tmp, lhs,
- )
- case "*image.NRGBA":
- fmt.Fprintf(buf, ""+
- "%si := %s\n"+
- "%sa%s := uint32(src.Pix[%si+3]) * 0x101\n"+
- "%sr%s := uint32(src.Pix[%si+0]) * %sa%s / 0xff\n"+
- "%sg%s := uint32(src.Pix[%si+1]) * %sa%s / 0xff\n"+
- "%sb%s := uint32(src.Pix[%si+2]) * %sa%s / 0xff\n",
- lhs, pixOffset("src", args[0], args[1], "*4", "*src.Stride"),
- lhs, tmp, lhs,
- lhs, tmp, lhs, lhs, tmp,
- lhs, tmp, lhs, lhs, tmp,
- lhs, tmp, lhs, lhs, tmp,
- )
- case "*image.RGBA":
- fmt.Fprintf(buf, ""+
- "%si := %s\n"+
- "%sr%s := uint32(src.Pix[%si+0]) * 0x101\n"+
- "%sg%s := uint32(src.Pix[%si+1]) * 0x101\n"+
- "%sb%s := uint32(src.Pix[%si+2]) * 0x101\n"+
- "%sa%s := uint32(src.Pix[%si+3]) * 0x101\n",
- lhs, pixOffset("src", args[0], args[1], "*4", "*src.Stride"),
- lhs, tmp, lhs,
- lhs, tmp, lhs,
- lhs, tmp, lhs,
- lhs, tmp, lhs,
- )
- case "*image.YCbCr":
- fmt.Fprintf(buf, ""+
- "%si := %s\n"+
- "%sj := %s\n"+
- "%s\n",
- lhs, pixOffset("src", args[0], args[1], "", "*src.YStride"),
- lhs, cOffset(args[0], args[1], d.sratio),
- ycbcrToRGB(lhs, tmp),
- )
- }
-
- if dollar == "srcf" {
- switch d.sType {
- default:
- fmt.Fprintf(buf, ""+
- "%sr %s float64(%sru)%s\n"+
- "%sg %s float64(%sgu)%s\n"+
- "%sb %s float64(%sbu)%s\n"+
- "%sa %s float64(%sau)%s\n",
- lhs, eqOp, lhs, extra,
- lhs, eqOp, lhs, extra,
- lhs, eqOp, lhs, extra,
- lhs, eqOp, lhs, extra,
- )
- case "*image.Gray":
- fmt.Fprintf(buf, ""+
- "%sr %s float64(%sru)%s\n",
- lhs, eqOp, lhs, extra,
- )
- case "*image.YCbCr":
- fmt.Fprintf(buf, ""+
- "%sr %s float64(%sru)%s\n"+
- "%sg %s float64(%sgu)%s\n"+
- "%sb %s float64(%sbu)%s\n",
- lhs, eqOp, lhs, extra,
- lhs, eqOp, lhs, extra,
- lhs, eqOp, lhs, extra,
- )
- }
- }
-
- return strings.TrimSpace(buf.String())
-
- case "tweakD":
- if d.dType == "*image.RGBA" {
- return "d += dst.Stride"
- }
- return ";"
-
- case "tweakDx":
- if d.dType == "*image.RGBA" {
- return strings.Replace(prefix, "dx++", "dx, d = dx+1, d+4", 1)
- }
- return prefix
-
- case "tweakDy":
- if d.dType == "*image.RGBA" {
- return strings.Replace(prefix, "for dy, s", "for _, s", 1)
- }
- return prefix
-
- case "tweakP":
- switch d.sType {
- case "*image.Gray":
- if strings.HasPrefix(strings.TrimSpace(prefix), "pa * ") {
- return "1,"
- }
- return "pr,"
- case "*image.YCbCr":
- if strings.HasPrefix(strings.TrimSpace(prefix), "pa * ") {
- return "1,"
- }
- }
- return prefix
-
- case "tweakPr":
- if d.sType == "*image.Gray" {
- return "pr *= s.invTotalWeightFFFF"
- }
- return ";"
-
- case "tweakVarP":
- switch d.sType {
- case "*image.Gray":
- return strings.Replace(prefix, "var pr, pg, pb, pa", "var pr", 1)
- case "*image.YCbCr":
- return strings.Replace(prefix, "var pr, pg, pb, pa", "var pr, pg, pb", 1)
- }
- return prefix
- }
- return ""
-}
-
-func expnSwitch(op, dType string, expandBoth bool, template string) string {
- if op == "" && dType != "anyDType" {
- lines := []string{"switch op {"}
- for _, op = range ops {
- lines = append(lines,
- fmt.Sprintf("case %s:", op),
- expnSwitch(op, dType, expandBoth, template),
- )
- }
- lines = append(lines, "}")
- return strings.Join(lines, "\n")
- }
-
- switchVar := "dst"
- if dType != "" {
- switchVar = "src"
- }
- lines := []string{fmt.Sprintf("switch %s := %s.(type) {", switchVar, switchVar)}
-
- fallback, values := "Image", dTypes
- if dType != "" {
- fallback, values = "image.Image", sTypesForDType[dType]
- }
- for _, v := range values {
- if dType != "" {
- // v is the sType. Skip those always-opaque sTypes, where Over is
- // equivalent to Src.
- if op == "Over" && alwaysOpaque[v] {
- continue
- }
- }
-
- if v == fallback {
- lines = append(lines, "default:")
- } else {
- lines = append(lines, fmt.Sprintf("case %s:", v))
- }
-
- if dType != "" {
- if v == "*image.YCbCr" {
- lines = append(lines, expnSwitchYCbCr(op, dType, template))
- } else {
- lines = append(lines, expnLine(template, &data{dType: dType, sType: v, op: op}))
- }
- } else if !expandBoth {
- lines = append(lines, expnLine(template, &data{dType: v, op: op}))
- } else {
- lines = append(lines, expnSwitch(op, v, false, template))
- }
- }
-
- lines = append(lines, "}")
- return strings.Join(lines, "\n")
-}
-
-func expnSwitchYCbCr(op, dType, template string) string {
- lines := []string{
- "switch src.SubsampleRatio {",
- "default:",
- expnLine(template, &data{dType: dType, sType: "image.Image", op: op}),
- }
- for _, sratio := range subsampleRatios {
- lines = append(lines,
- fmt.Sprintf("case image.YCbCrSubsampleRatio%s:", sratio),
- expnLine(template, &data{dType: dType, sType: "*image.YCbCr", sratio: sratio, op: op}),
- )
- }
- lines = append(lines, "}")
- return strings.Join(lines, "\n")
-}
-
-func argf(args []string, s string) string {
- if len(args) > 9 {
- panic("too many args")
- }
- for i, a := range args {
- old := fmt.Sprintf("$%d", i)
- s = strings.Replace(s, old, a, -1)
- }
- return s
-}
-
-func pixOffset(m, x, y, xstride, ystride string) string {
- return fmt.Sprintf("(%s-%s.Rect.Min.Y)%s + (%s-%s.Rect.Min.X)%s", y, m, ystride, x, m, xstride)
-}
-
-func cOffset(x, y, sratio string) string {
- switch sratio {
- case "444":
- return fmt.Sprintf("( %s - src.Rect.Min.Y )*src.CStride + ( %s - src.Rect.Min.X )", y, x)
- case "422":
- return fmt.Sprintf("( %s - src.Rect.Min.Y )*src.CStride + ((%s)/2 - src.Rect.Min.X/2)", y, x)
- case "420":
- return fmt.Sprintf("((%s)/2 - src.Rect.Min.Y/2)*src.CStride + ((%s)/2 - src.Rect.Min.X/2)", y, x)
- case "440":
- return fmt.Sprintf("((%s)/2 - src.Rect.Min.Y/2)*src.CStride + ( %s - src.Rect.Min.X )", y, x)
- }
- return fmt.Sprintf("unsupported sratio %q", sratio)
-}
-
-func ycbcrToRGB(lhs, tmp string) string {
- s := `
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- $yy1 := int(src.Y[$i]) * 0x10101
- $cb1 := int(src.Cb[$j]) - 128
- $cr1 := int(src.Cr[$j]) - 128
- $r@ := ($yy1 + 91881*$cr1) >> 8
- $g@ := ($yy1 - 22554*$cb1 - 46802*$cr1) >> 8
- $b@ := ($yy1 + 116130*$cb1) >> 8
- if $r@ < 0 {
- $r@ = 0
- } else if $r@ > 0xffff {
- $r@ = 0xffff
- }
- if $g@ < 0 {
- $g@ = 0
- } else if $g@ > 0xffff {
- $g@ = 0xffff
- }
- if $b@ < 0 {
- $b@ = 0
- } else if $b@ > 0xffff {
- $b@ = 0xffff
- }
- `
- s = strings.Replace(s, "$", lhs, -1)
- s = strings.Replace(s, "@", tmp, -1)
- return s
-}
-
-func split(s, sep string) (string, string) {
- if i := strings.Index(s, sep); i >= 0 {
- return strings.TrimSpace(s[:i]), strings.TrimSpace(s[i+len(sep):])
- }
- return "", ""
-}
-
-func splitEq(s string) (lhs, eqOp string) {
- s = strings.TrimSpace(s)
- if lhs, _ = split(s, ":="); lhs != "" {
- return lhs, ":="
- }
- if lhs, _ = split(s, "+="); lhs != "" {
- return lhs, "+="
- }
- return "", ""
-}
-
-func splitArgs(s string) (args []string, extra string) {
- s = strings.TrimSpace(s)
- if s == "" || s[0] != '[' {
- return nil, ""
- }
- s = s[1:]
-
- i := strings.IndexByte(s, ']')
- if i < 0 {
- return nil, ""
- }
- args, extra = strings.Split(s[:i], ","), s[i+1:]
- for i := range args {
- args[i] = strings.TrimSpace(args[i])
- }
- return args, extra
-}
-
-func relName(s string) string {
- if i := strings.LastIndex(s, "."); i >= 0 {
- return s[i+1:]
- }
- return s
-}
-
-const (
- codeRoot = `
- func (z $receiver) Scale(dst Image, dr image.Rectangle, src image.Image, sr image.Rectangle, op Op, opts *Options) {
- // Try to simplify a Scale to a Copy when DstMask is not specified.
- // If DstMask is not nil, Copy will call Scale back with same dr and sr, and cause stack overflow.
- if dr.Size() == sr.Size() && (opts == nil || opts.DstMask == nil) {
- Copy(dst, dr.Min, src, sr, op, opts)
- return
- }
-
- var o Options
- if opts != nil {
- o = *opts
- }
-
- // adr is the affected destination pixels.
- adr := dst.Bounds().Intersect(dr)
- adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
- if adr.Empty() || sr.Empty() {
- return
- }
- // Make adr relative to dr.Min.
- adr = adr.Sub(dr.Min)
- if op == Over && o.SrcMask == nil && opaque(src) {
- op = Src
- }
-
- // sr is the source pixels. If it extends beyond the src bounds,
- // we cannot use the type-specific fast paths, as they access
- // the Pix fields directly without bounds checking.
- //
- // Similarly, the fast paths assume that the masks are nil.
- if o.DstMask != nil || o.SrcMask != nil || !sr.In(src.Bounds()) {
- switch op {
- case Over:
- z.scale_Image_Image_Over(dst, dr, adr, src, sr, &o)
- case Src:
- z.scale_Image_Image_Src(dst, dr, adr, src, sr, &o)
- }
- } else if _, ok := src.(*image.Uniform); ok {
- Draw(dst, dr, src, src.Bounds().Min, op)
- } else {
- $switch z.scale_$dTypeRN_$sTypeRN$sratio_$op(dst, dr, adr, src, sr, &o)
- }
- }
-
- func (z $receiver) Transform(dst Image, s2d f64.Aff3, src image.Image, sr image.Rectangle, op Op, opts *Options) {
- // Try to simplify a Transform to a Copy.
- if s2d[0] == 1 && s2d[1] == 0 && s2d[3] == 0 && s2d[4] == 1 {
- dx := int(s2d[2])
- dy := int(s2d[5])
- if float64(dx) == s2d[2] && float64(dy) == s2d[5] {
- Copy(dst, image.Point{X: sr.Min.X + dx, Y: sr.Min.X + dy}, src, sr, op, opts)
- return
- }
- }
-
- var o Options
- if opts != nil {
- o = *opts
- }
-
- dr := transformRect(&s2d, &sr)
- // adr is the affected destination pixels.
- adr := dst.Bounds().Intersect(dr)
- adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
- if adr.Empty() || sr.Empty() {
- return
- }
- if op == Over && o.SrcMask == nil && opaque(src) {
- op = Src
- }
-
- d2s := invert(&s2d)
- // bias is a translation of the mapping from dst coordinates to src
- // coordinates such that the latter temporarily have non-negative X
- // and Y coordinates. This allows us to write int(f) instead of
- // int(math.Floor(f)), since "round to zero" and "round down" are
- // equivalent when f >= 0, but the former is much cheaper. The X--
- // and Y-- are because the TransformLeaf methods have a "sx -= 0.5"
- // adjustment.
- bias := transformRect(&d2s, &adr).Min
- bias.X--
- bias.Y--
- d2s[2] -= float64(bias.X)
- d2s[5] -= float64(bias.Y)
- // Make adr relative to dr.Min.
- adr = adr.Sub(dr.Min)
- // sr is the source pixels. If it extends beyond the src bounds,
- // we cannot use the type-specific fast paths, as they access
- // the Pix fields directly without bounds checking.
- //
- // Similarly, the fast paths assume that the masks are nil.
- if o.DstMask != nil || o.SrcMask != nil || !sr.In(src.Bounds()) {
- switch op {
- case Over:
- z.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
- case Src:
- z.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
- }
- } else if u, ok := src.(*image.Uniform); ok {
- transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, op)
- } else {
- $switch z.transform_$dTypeRN_$sTypeRN$sratio_$op(dst, dr, adr, &d2s, src, sr, bias, &o)
- }
- }
- `
-
- codeNNScaleLeaf = `
- func (nnInterpolator) scale_$dTypeRN_$sTypeRN$sratio_$op(dst $dType, dr, adr image.Rectangle, src $sType, sr image.Rectangle, opts *Options) {
- dw2 := uint64(dr.Dx()) * 2
- dh2 := uint64(dr.Dy()) * 2
- sw := uint64(sr.Dx())
- sh := uint64(sr.Dy())
- $preOuter
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (2*uint64(dy) + 1) * sh / dh2
- $preInner
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ { $tweakDx
- sx := (2*uint64(dx) + 1) * sw / dw2
- p := $srcu[sr.Min.X + int(sx), sr.Min.Y + int(sy)]
- $outputu[dr.Min.X + int(dx), dr.Min.Y + int(dy), p]
- }
- }
- }
- `
-
- codeNNTransformLeaf = `
- func (nnInterpolator) transform_$dTypeRN_$sTypeRN$sratio_$op(dst $dType, dr, adr image.Rectangle, d2s *f64.Aff3, src $sType, sr image.Rectangle, bias image.Point, opts *Options) {
- $preOuter
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y + int(dy)) + 0.5
- $preInner
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ { $tweakDx
- dxf := float64(dr.Min.X + int(dx)) + 0.5
- sx0 := int(d2s[0]*dxf + d2s[1]*dyf + d2s[2]) + bias.X
- sy0 := int(d2s[3]*dxf + d2s[4]*dyf + d2s[5]) + bias.Y
- if !(image.Point{sx0, sy0}).In(sr) {
- continue
- }
- p := $srcu[sx0, sy0]
- $outputu[dr.Min.X + int(dx), dr.Min.Y + int(dy), p]
- }
- }
- }
- `
-
- codeABLScaleLeaf = `
- func (ablInterpolator) scale_$dTypeRN_$sTypeRN$sratio_$op(dst $dType, dr, adr image.Rectangle, src $sType, sr image.Rectangle, opts *Options) {
- sw := int32(sr.Dx())
- sh := int32(sr.Dy())
- yscale := float64(sh) / float64(dr.Dy())
- xscale := float64(sw) / float64(dr.Dx())
- swMinus1, shMinus1 := sw - 1, sh - 1
- $preOuter
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (float64(dy)+0.5)*yscale - 0.5
- // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
- // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
- // sx, below.
- sy0 := int32(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy1 := sy0 + 1
- if sy < 0 {
- sy0, sy1 = 0, 0
- yFrac0, yFrac1 = 0, 1
- } else if sy1 > shMinus1 {
- sy0, sy1 = shMinus1, shMinus1
- yFrac0, yFrac1 = 1, 0
- }
- $preInner
-
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ { $tweakDx
- sx := (float64(dx)+0.5)*xscale - 0.5
- sx0 := int32(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx1 := sx0 + 1
- if sx < 0 {
- sx0, sx1 = 0, 0
- xFrac0, xFrac1 = 0, 1
- } else if sx1 > swMinus1 {
- sx0, sx1 = swMinus1, swMinus1
- xFrac0, xFrac1 = 1, 0
- }
-
- s00 := $srcf[sr.Min.X + int(sx0), sr.Min.Y + int(sy0)]
- s10 := $srcf[sr.Min.X + int(sx1), sr.Min.Y + int(sy0)]
- $blend[xFrac1, s00, xFrac0, s10]
- s01 := $srcf[sr.Min.X + int(sx0), sr.Min.Y + int(sy1)]
- s11 := $srcf[sr.Min.X + int(sx1), sr.Min.Y + int(sy1)]
- $blend[xFrac1, s01, xFrac0, s11]
- $blend[yFrac1, s10, yFrac0, s11]
- $convFtou[p, s11]
- $outputu[dr.Min.X + int(dx), dr.Min.Y + int(dy), p]
- }
- }
- }
- `
-
- codeABLTransformLeaf = `
- func (ablInterpolator) transform_$dTypeRN_$sTypeRN$sratio_$op(dst $dType, dr, adr image.Rectangle, d2s *f64.Aff3, src $sType, sr image.Rectangle, bias image.Point, opts *Options) {
- $preOuter
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y + int(dy)) + 0.5
- $preInner
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ { $tweakDx
- dxf := float64(dr.Min.X + int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- sx -= 0.5
- sx0 := int(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx0 += bias.X
- sx1 := sx0 + 1
- if sx0 < sr.Min.X {
- sx0, sx1 = sr.Min.X, sr.Min.X
- xFrac0, xFrac1 = 0, 1
- } else if sx1 >= sr.Max.X {
- sx0, sx1 = sr.Max.X-1, sr.Max.X-1
- xFrac0, xFrac1 = 1, 0
- }
-
- sy -= 0.5
- sy0 := int(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy0 += bias.Y
- sy1 := sy0 + 1
- if sy0 < sr.Min.Y {
- sy0, sy1 = sr.Min.Y, sr.Min.Y
- yFrac0, yFrac1 = 0, 1
- } else if sy1 >= sr.Max.Y {
- sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
- yFrac0, yFrac1 = 1, 0
- }
-
- s00 := $srcf[sx0, sy0]
- s10 := $srcf[sx1, sy0]
- $blend[xFrac1, s00, xFrac0, s10]
- s01 := $srcf[sx0, sy1]
- s11 := $srcf[sx1, sy1]
- $blend[xFrac1, s01, xFrac0, s11]
- $blend[yFrac1, s10, yFrac0, s11]
- $convFtou[p, s11]
- $outputu[dr.Min.X + int(dx), dr.Min.Y + int(dy), p]
- }
- }
- }
- `
-
- codeKernelRoot = `
- func (z *kernelScaler) Scale(dst Image, dr image.Rectangle, src image.Image, sr image.Rectangle, op Op, opts *Options) {
- if z.dw != int32(dr.Dx()) || z.dh != int32(dr.Dy()) || z.sw != int32(sr.Dx()) || z.sh != int32(sr.Dy()) {
- z.kernel.Scale(dst, dr, src, sr, op, opts)
- return
- }
-
- var o Options
- if opts != nil {
- o = *opts
- }
-
- // adr is the affected destination pixels.
- adr := dst.Bounds().Intersect(dr)
- adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
- if adr.Empty() || sr.Empty() {
- return
- }
- // Make adr relative to dr.Min.
- adr = adr.Sub(dr.Min)
- if op == Over && o.SrcMask == nil && opaque(src) {
- op = Src
- }
-
- if _, ok := src.(*image.Uniform); ok && o.DstMask == nil && o.SrcMask == nil && sr.In(src.Bounds()) {
- Draw(dst, dr, src, src.Bounds().Min, op)
- return
- }
-
- // Create a temporary buffer:
- // scaleX distributes the source image's columns over the temporary image.
- // scaleY distributes the temporary image's rows over the destination image.
- var tmp [][4]float64
- if z.pool.New != nil {
- tmpp := z.pool.Get().(*[][4]float64)
- defer z.pool.Put(tmpp)
- tmp = *tmpp
- } else {
- tmp = z.makeTmpBuf()
- }
-
- // sr is the source pixels. If it extends beyond the src bounds,
- // we cannot use the type-specific fast paths, as they access
- // the Pix fields directly without bounds checking.
- //
- // Similarly, the fast paths assume that the masks are nil.
- if o.SrcMask != nil || !sr.In(src.Bounds()) {
- z.scaleX_Image(tmp, src, sr, &o)
- } else {
- $switchS z.scaleX_$sTypeRN$sratio(tmp, src, sr, &o)
- }
-
- if o.DstMask != nil {
- switch op {
- case Over:
- z.scaleY_Image_Over(dst, dr, adr, tmp, &o)
- case Src:
- z.scaleY_Image_Src(dst, dr, adr, tmp, &o)
- }
- } else {
- $switchD z.scaleY_$dTypeRN_$op(dst, dr, adr, tmp, &o)
- }
- }
-
- func (q *Kernel) Transform(dst Image, s2d f64.Aff3, src image.Image, sr image.Rectangle, op Op, opts *Options) {
- var o Options
- if opts != nil {
- o = *opts
- }
-
- dr := transformRect(&s2d, &sr)
- // adr is the affected destination pixels.
- adr := dst.Bounds().Intersect(dr)
- adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
- if adr.Empty() || sr.Empty() {
- return
- }
- if op == Over && o.SrcMask == nil && opaque(src) {
- op = Src
- }
- d2s := invert(&s2d)
- // bias is a translation of the mapping from dst coordinates to src
- // coordinates such that the latter temporarily have non-negative X
- // and Y coordinates. This allows us to write int(f) instead of
- // int(math.Floor(f)), since "round to zero" and "round down" are
- // equivalent when f >= 0, but the former is much cheaper. The X--
- // and Y-- are because the TransformLeaf methods have a "sx -= 0.5"
- // adjustment.
- bias := transformRect(&d2s, &adr).Min
- bias.X--
- bias.Y--
- d2s[2] -= float64(bias.X)
- d2s[5] -= float64(bias.Y)
- // Make adr relative to dr.Min.
- adr = adr.Sub(dr.Min)
-
- if u, ok := src.(*image.Uniform); ok && o.DstMask != nil && o.SrcMask != nil && sr.In(src.Bounds()) {
- transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, op)
- return
- }
-
- xscale := abs(d2s[0])
- if s := abs(d2s[1]); xscale < s {
- xscale = s
- }
- yscale := abs(d2s[3])
- if s := abs(d2s[4]); yscale < s {
- yscale = s
- }
-
- // sr is the source pixels. If it extends beyond the src bounds,
- // we cannot use the type-specific fast paths, as they access
- // the Pix fields directly without bounds checking.
- //
- // Similarly, the fast paths assume that the masks are nil.
- if o.DstMask != nil || o.SrcMask != nil || !sr.In(src.Bounds()) {
- switch op {
- case Over:
- q.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
- case Src:
- q.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
- }
- } else {
- $switch q.transform_$dTypeRN_$sTypeRN$sratio_$op(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
- }
- }
- `
-
- codeKernelScaleLeafX = `
- func (z *kernelScaler) scaleX_$sTypeRN$sratio(tmp [][4]float64, src $sType, sr image.Rectangle, opts *Options) {
- t := 0
- $preKernelOuter
- for y := int32(0); y < z.sh; y++ {
- for _, s := range z.horizontal.sources {
- var pr, pg, pb, pa float64 $tweakVarP
- for _, c := range z.horizontal.contribs[s.i:s.j] {
- p += $srcf[sr.Min.X + int(c.coord), sr.Min.Y + int(y)] * c.weight
- }
- $tweakPr
- tmp[t] = [4]float64{
- pr * s.invTotalWeightFFFF, $tweakP
- pg * s.invTotalWeightFFFF, $tweakP
- pb * s.invTotalWeightFFFF, $tweakP
- pa * s.invTotalWeightFFFF, $tweakP
- }
- t++
- }
- }
- }
- `
-
- codeKernelScaleLeafY = `
- func (z *kernelScaler) scaleY_$dTypeRN_$op(dst $dType, dr, adr image.Rectangle, tmp [][4]float64, opts *Options) {
- $preOuter
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
- $preKernelInner
- for dy, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] { $tweakDy
- var pr, pg, pb, pa float64
- for _, c := range z.vertical.contribs[s.i:s.j] {
- p := &tmp[c.coord*z.dw+dx]
- pr += p[0] * c.weight
- pg += p[1] * c.weight
- pb += p[2] * c.weight
- pa += p[3] * c.weight
- }
- $clampToAlpha
- $outputf[dr.Min.X + int(dx), dr.Min.Y + int(adr.Min.Y + dy), ftou, p, s.invTotalWeight]
- $tweakD
- }
- }
- }
- `
-
- codeKernelTransformLeaf = `
- func (q *Kernel) transform_$dTypeRN_$sTypeRN$sratio_$op(dst $dType, dr, adr image.Rectangle, d2s *f64.Aff3, src $sType, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
- // When shrinking, broaden the effective kernel support so that we still
- // visit every source pixel.
- xHalfWidth, xKernelArgScale := q.Support, 1.0
- if xscale > 1 {
- xHalfWidth *= xscale
- xKernelArgScale = 1 / xscale
- }
- yHalfWidth, yKernelArgScale := q.Support, 1.0
- if yscale > 1 {
- yHalfWidth *= yscale
- yKernelArgScale = 1 / yscale
- }
-
- xWeights := make([]float64, 1 + 2*int(math.Ceil(xHalfWidth)))
- yWeights := make([]float64, 1 + 2*int(math.Ceil(yHalfWidth)))
-
- $preOuter
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y + int(dy)) + 0.5
- $preInner
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ { $tweakDx
- dxf := float64(dr.Min.X + int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- // TODO: adjust the bias so that we can use int(f) instead
- // of math.Floor(f) and math.Ceil(f).
- sx += float64(bias.X)
- sx -= 0.5
- ix := int(math.Floor(sx - xHalfWidth))
- if ix < sr.Min.X {
- ix = sr.Min.X
- }
- jx := int(math.Ceil(sx + xHalfWidth))
- if jx > sr.Max.X {
- jx = sr.Max.X
- }
-
- totalXWeight := 0.0
- for kx := ix; kx < jx; kx++ {
- xWeight := 0.0
- if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
- xWeight = q.At(t)
- }
- xWeights[kx - ix] = xWeight
- totalXWeight += xWeight
- }
- for x := range xWeights[:jx-ix] {
- xWeights[x] /= totalXWeight
- }
-
- sy += float64(bias.Y)
- sy -= 0.5
- iy := int(math.Floor(sy - yHalfWidth))
- if iy < sr.Min.Y {
- iy = sr.Min.Y
- }
- jy := int(math.Ceil(sy + yHalfWidth))
- if jy > sr.Max.Y {
- jy = sr.Max.Y
- }
-
- totalYWeight := 0.0
- for ky := iy; ky < jy; ky++ {
- yWeight := 0.0
- if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
- yWeight = q.At(t)
- }
- yWeights[ky - iy] = yWeight
- totalYWeight += yWeight
- }
- for y := range yWeights[:jy-iy] {
- yWeights[y] /= totalYWeight
- }
-
- var pr, pg, pb, pa float64 $tweakVarP
- for ky := iy; ky < jy; ky++ {
- if yWeight := yWeights[ky - iy]; yWeight != 0 {
- for kx := ix; kx < jx; kx++ {
- if w := xWeights[kx - ix] * yWeight; w != 0 {
- p += $srcf[kx, ky] * w
- }
- }
- }
- }
- $clampToAlpha
- $outputf[dr.Min.X + int(dx), dr.Min.Y + int(dy), fffftou, p, 1]
- }
- }
- }
- `
-)
diff --git a/vendor/golang.org/x/image/draw/go1_8.go b/vendor/golang.org/x/image/draw/go1_8.go
deleted file mode 100644
index ec192b7..0000000
--- a/vendor/golang.org/x/image/draw/go1_8.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build !go1.9,!go1.8.typealias
-
-package draw
-
-import (
- "image"
- "image/color"
- "image/draw"
-)
-
-// Drawer contains the Draw method.
-type Drawer interface {
- // Draw aligns r.Min in dst with sp in src and then replaces the
- // rectangle r in dst with the result of drawing src on dst.
- Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point)
-}
-
-// Image is an image.Image with a Set method to change a single pixel.
-type Image interface {
- image.Image
- Set(x, y int, c color.Color)
-}
-
-// Op is a Porter-Duff compositing operator.
-type Op int
-
-const (
- // Over specifies ``(src in mask) over dst''.
- Over Op = Op(draw.Over)
- // Src specifies ``src in mask''.
- Src Op = Op(draw.Src)
-)
-
-// Draw implements the Drawer interface by calling the Draw function with
-// this Op.
-func (op Op) Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point) {
- (draw.Op(op)).Draw(dst, r, src, sp)
-}
-
-// Quantizer produces a palette for an image.
-type Quantizer interface {
- // Quantize appends up to cap(p) - len(p) colors to p and returns the
- // updated palette suitable for converting m to a paletted image.
- Quantize(p color.Palette, m image.Image) color.Palette
-}
diff --git a/vendor/golang.org/x/image/draw/go1_9.go b/vendor/golang.org/x/image/draw/go1_9.go
deleted file mode 100644
index fc548e9..0000000
--- a/vendor/golang.org/x/image/draw/go1_9.go
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2016 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build go1.9 go1.8.typealias
-
-package draw
-
-import (
- "image/draw"
-)
-
-// We use type aliases (new in Go 1.9) for the exported names from the standard
-// library's image/draw package. This is not merely syntactic sugar for
-//
-// type Drawer draw.Drawer
-//
-// as aliasing means that the types in this package, such as draw.Image and
-// draw.Op, are identical to the corresponding draw.Image and draw.Op types in
-// the standard library. In comparison, prior to Go 1.9, the code in go1_8.go
-// defines new types that mimic the old but are different types.
-//
-// The package documentation, in draw.go, explicitly gives the intent of this
-// package:
-//
-// This package is a superset of and a drop-in replacement for the
-// image/draw package in the standard library.
-//
-// Drop-in replacement means that I can replace all of my "image/draw" imports
-// with "golang.org/x/image/draw", to access additional features in this
-// package, and no further changes are required. That's mostly true, but not
-// completely true unless we use type aliases.
-//
-// Without type aliases, users might need to import both "image/draw" and
-// "golang.org/x/image/draw" in order to convert from two conceptually
-// equivalent but different (from the compiler's point of view) types, such as
-// from one draw.Op type to another draw.Op type, to satisfy some other
-// interface or function signature.
-
-// Drawer contains the Draw method.
-type Drawer = draw.Drawer
-
-// Image is an image.Image with a Set method to change a single pixel.
-type Image = draw.Image
-
-// Op is a Porter-Duff compositing operator.
-type Op = draw.Op
-
-const (
- // Over specifies ``(src in mask) over dst''.
- Over Op = draw.Over
- // Src specifies ``src in mask''.
- Src Op = draw.Src
-)
-
-// Quantizer produces a palette for an image.
-type Quantizer = draw.Quantizer
diff --git a/vendor/golang.org/x/image/draw/impl.go b/vendor/golang.org/x/image/draw/impl.go
deleted file mode 100644
index 75498ad..0000000
--- a/vendor/golang.org/x/image/draw/impl.go
+++ /dev/null
@@ -1,6670 +0,0 @@
-// generated by "go run gen.go". DO NOT EDIT.
-
-package draw
-
-import (
- "image"
- "image/color"
- "math"
-
- "golang.org/x/image/math/f64"
-)
-
-func (z nnInterpolator) Scale(dst Image, dr image.Rectangle, src image.Image, sr image.Rectangle, op Op, opts *Options) {
- // Try to simplify a Scale to a Copy when DstMask is not specified.
- // If DstMask is not nil, Copy will call Scale back with same dr and sr, and cause stack overflow.
- if dr.Size() == sr.Size() && (opts == nil || opts.DstMask == nil) {
- Copy(dst, dr.Min, src, sr, op, opts)
- return
- }
-
- var o Options
- if opts != nil {
- o = *opts
- }
-
- // adr is the affected destination pixels.
- adr := dst.Bounds().Intersect(dr)
- adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
- if adr.Empty() || sr.Empty() {
- return
- }
- // Make adr relative to dr.Min.
- adr = adr.Sub(dr.Min)
- if op == Over && o.SrcMask == nil && opaque(src) {
- op = Src
- }
-
- // sr is the source pixels. If it extends beyond the src bounds,
- // we cannot use the type-specific fast paths, as they access
- // the Pix fields directly without bounds checking.
- //
- // Similarly, the fast paths assume that the masks are nil.
- if o.DstMask != nil || o.SrcMask != nil || !sr.In(src.Bounds()) {
- switch op {
- case Over:
- z.scale_Image_Image_Over(dst, dr, adr, src, sr, &o)
- case Src:
- z.scale_Image_Image_Src(dst, dr, adr, src, sr, &o)
- }
- } else if _, ok := src.(*image.Uniform); ok {
- Draw(dst, dr, src, src.Bounds().Min, op)
- } else {
- switch op {
- case Over:
- switch dst := dst.(type) {
- case *image.RGBA:
- switch src := src.(type) {
- case *image.NRGBA:
- z.scale_RGBA_NRGBA_Over(dst, dr, adr, src, sr, &o)
- case *image.RGBA:
- z.scale_RGBA_RGBA_Over(dst, dr, adr, src, sr, &o)
- default:
- z.scale_RGBA_Image_Over(dst, dr, adr, src, sr, &o)
- }
- default:
- switch src := src.(type) {
- default:
- z.scale_Image_Image_Over(dst, dr, adr, src, sr, &o)
- }
- }
- case Src:
- switch dst := dst.(type) {
- case *image.RGBA:
- switch src := src.(type) {
- case *image.Gray:
- z.scale_RGBA_Gray_Src(dst, dr, adr, src, sr, &o)
- case *image.NRGBA:
- z.scale_RGBA_NRGBA_Src(dst, dr, adr, src, sr, &o)
- case *image.RGBA:
- z.scale_RGBA_RGBA_Src(dst, dr, adr, src, sr, &o)
- case *image.YCbCr:
- switch src.SubsampleRatio {
- default:
- z.scale_RGBA_Image_Src(dst, dr, adr, src, sr, &o)
- case image.YCbCrSubsampleRatio444:
- z.scale_RGBA_YCbCr444_Src(dst, dr, adr, src, sr, &o)
- case image.YCbCrSubsampleRatio422:
- z.scale_RGBA_YCbCr422_Src(dst, dr, adr, src, sr, &o)
- case image.YCbCrSubsampleRatio420:
- z.scale_RGBA_YCbCr420_Src(dst, dr, adr, src, sr, &o)
- case image.YCbCrSubsampleRatio440:
- z.scale_RGBA_YCbCr440_Src(dst, dr, adr, src, sr, &o)
- }
- default:
- z.scale_RGBA_Image_Src(dst, dr, adr, src, sr, &o)
- }
- default:
- switch src := src.(type) {
- default:
- z.scale_Image_Image_Src(dst, dr, adr, src, sr, &o)
- }
- }
- }
- }
-}
-
-func (z nnInterpolator) Transform(dst Image, s2d f64.Aff3, src image.Image, sr image.Rectangle, op Op, opts *Options) {
- // Try to simplify a Transform to a Copy.
- if s2d[0] == 1 && s2d[1] == 0 && s2d[3] == 0 && s2d[4] == 1 {
- dx := int(s2d[2])
- dy := int(s2d[5])
- if float64(dx) == s2d[2] && float64(dy) == s2d[5] {
- Copy(dst, image.Point{X: sr.Min.X + dx, Y: sr.Min.X + dy}, src, sr, op, opts)
- return
- }
- }
-
- var o Options
- if opts != nil {
- o = *opts
- }
-
- dr := transformRect(&s2d, &sr)
- // adr is the affected destination pixels.
- adr := dst.Bounds().Intersect(dr)
- adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
- if adr.Empty() || sr.Empty() {
- return
- }
- if op == Over && o.SrcMask == nil && opaque(src) {
- op = Src
- }
-
- d2s := invert(&s2d)
- // bias is a translation of the mapping from dst coordinates to src
- // coordinates such that the latter temporarily have non-negative X
- // and Y coordinates. This allows us to write int(f) instead of
- // int(math.Floor(f)), since "round to zero" and "round down" are
- // equivalent when f >= 0, but the former is much cheaper. The X--
- // and Y-- are because the TransformLeaf methods have a "sx -= 0.5"
- // adjustment.
- bias := transformRect(&d2s, &adr).Min
- bias.X--
- bias.Y--
- d2s[2] -= float64(bias.X)
- d2s[5] -= float64(bias.Y)
- // Make adr relative to dr.Min.
- adr = adr.Sub(dr.Min)
- // sr is the source pixels. If it extends beyond the src bounds,
- // we cannot use the type-specific fast paths, as they access
- // the Pix fields directly without bounds checking.
- //
- // Similarly, the fast paths assume that the masks are nil.
- if o.DstMask != nil || o.SrcMask != nil || !sr.In(src.Bounds()) {
- switch op {
- case Over:
- z.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
- case Src:
- z.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
- }
- } else if u, ok := src.(*image.Uniform); ok {
- transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, op)
- } else {
- switch op {
- case Over:
- switch dst := dst.(type) {
- case *image.RGBA:
- switch src := src.(type) {
- case *image.NRGBA:
- z.transform_RGBA_NRGBA_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
- case *image.RGBA:
- z.transform_RGBA_RGBA_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
- default:
- z.transform_RGBA_Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
- }
- default:
- switch src := src.(type) {
- default:
- z.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
- }
- }
- case Src:
- switch dst := dst.(type) {
- case *image.RGBA:
- switch src := src.(type) {
- case *image.Gray:
- z.transform_RGBA_Gray_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
- case *image.NRGBA:
- z.transform_RGBA_NRGBA_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
- case *image.RGBA:
- z.transform_RGBA_RGBA_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
- case *image.YCbCr:
- switch src.SubsampleRatio {
- default:
- z.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
- case image.YCbCrSubsampleRatio444:
- z.transform_RGBA_YCbCr444_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
- case image.YCbCrSubsampleRatio422:
- z.transform_RGBA_YCbCr422_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
- case image.YCbCrSubsampleRatio420:
- z.transform_RGBA_YCbCr420_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
- case image.YCbCrSubsampleRatio440:
- z.transform_RGBA_YCbCr440_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
- }
- default:
- z.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
- }
- default:
- switch src := src.(type) {
- default:
- z.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
- }
- }
- }
- }
-}
-
-func (nnInterpolator) scale_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.Gray, sr image.Rectangle, opts *Options) {
- dw2 := uint64(dr.Dx()) * 2
- dh2 := uint64(dr.Dy()) * 2
- sw := uint64(sr.Dx())
- sh := uint64(sr.Dy())
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (2*uint64(dy) + 1) * sh / dh2
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (2*uint64(dx) + 1) * sw / dw2
- pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(sx) - src.Rect.Min.X)
- pr := uint32(src.Pix[pi]) * 0x101
- out := uint8(pr >> 8)
- dst.Pix[d+0] = out
- dst.Pix[d+1] = out
- dst.Pix[d+2] = out
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (nnInterpolator) scale_RGBA_NRGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, src *image.NRGBA, sr image.Rectangle, opts *Options) {
- dw2 := uint64(dr.Dx()) * 2
- dh2 := uint64(dr.Dy()) * 2
- sw := uint64(sr.Dx())
- sh := uint64(sr.Dy())
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (2*uint64(dy) + 1) * sh / dh2
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (2*uint64(dx) + 1) * sw / dw2
- pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx)-src.Rect.Min.X)*4
- pa := uint32(src.Pix[pi+3]) * 0x101
- pr := uint32(src.Pix[pi+0]) * pa / 0xff
- pg := uint32(src.Pix[pi+1]) * pa / 0xff
- pb := uint32(src.Pix[pi+2]) * pa / 0xff
- pa1 := (0xffff - pa) * 0x101
- dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
- dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
- dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
- dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
- }
- }
-}
-
-func (nnInterpolator) scale_RGBA_NRGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.NRGBA, sr image.Rectangle, opts *Options) {
- dw2 := uint64(dr.Dx()) * 2
- dh2 := uint64(dr.Dy()) * 2
- sw := uint64(sr.Dx())
- sh := uint64(sr.Dy())
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (2*uint64(dy) + 1) * sh / dh2
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (2*uint64(dx) + 1) * sw / dw2
- pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx)-src.Rect.Min.X)*4
- pa := uint32(src.Pix[pi+3]) * 0x101
- pr := uint32(src.Pix[pi+0]) * pa / 0xff
- pg := uint32(src.Pix[pi+1]) * pa / 0xff
- pb := uint32(src.Pix[pi+2]) * pa / 0xff
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = uint8(pa >> 8)
- }
- }
-}
-
-func (nnInterpolator) scale_RGBA_RGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, src *image.RGBA, sr image.Rectangle, opts *Options) {
- dw2 := uint64(dr.Dx()) * 2
- dh2 := uint64(dr.Dy()) * 2
- sw := uint64(sr.Dx())
- sh := uint64(sr.Dy())
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (2*uint64(dy) + 1) * sh / dh2
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (2*uint64(dx) + 1) * sw / dw2
- pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx)-src.Rect.Min.X)*4
- pr := uint32(src.Pix[pi+0]) * 0x101
- pg := uint32(src.Pix[pi+1]) * 0x101
- pb := uint32(src.Pix[pi+2]) * 0x101
- pa := uint32(src.Pix[pi+3]) * 0x101
- pa1 := (0xffff - pa) * 0x101
- dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
- dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
- dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
- dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
- }
- }
-}
-
-func (nnInterpolator) scale_RGBA_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.RGBA, sr image.Rectangle, opts *Options) {
- dw2 := uint64(dr.Dx()) * 2
- dh2 := uint64(dr.Dy()) * 2
- sw := uint64(sr.Dx())
- sh := uint64(sr.Dy())
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (2*uint64(dy) + 1) * sh / dh2
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (2*uint64(dx) + 1) * sw / dw2
- pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx)-src.Rect.Min.X)*4
- pr := uint32(src.Pix[pi+0]) * 0x101
- pg := uint32(src.Pix[pi+1]) * 0x101
- pb := uint32(src.Pix[pi+2]) * 0x101
- pa := uint32(src.Pix[pi+3]) * 0x101
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = uint8(pa >> 8)
- }
- }
-}
-
-func (nnInterpolator) scale_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) {
- dw2 := uint64(dr.Dx()) * 2
- dh2 := uint64(dr.Dy()) * 2
- sw := uint64(sr.Dx())
- sh := uint64(sr.Dy())
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (2*uint64(dy) + 1) * sh / dh2
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (2*uint64(dx) + 1) * sw / dw2
- pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
- pj := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10101
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pr := (pyy1 + 91881*pcr1) >> 8
- pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pb := (pyy1 + 116130*pcb1) >> 8
- if pr < 0 {
- pr = 0
- } else if pr > 0xffff {
- pr = 0xffff
- }
- if pg < 0 {
- pg = 0
- } else if pg > 0xffff {
- pg = 0xffff
- }
- if pb < 0 {
- pb = 0
- } else if pb > 0xffff {
- pb = 0xffff
- }
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (nnInterpolator) scale_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) {
- dw2 := uint64(dr.Dx()) * 2
- dh2 := uint64(dr.Dy()) * 2
- sw := uint64(sr.Dx())
- sh := uint64(sr.Dy())
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (2*uint64(dy) + 1) * sh / dh2
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (2*uint64(dx) + 1) * sw / dw2
- pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
- pj := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx))/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10101
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pr := (pyy1 + 91881*pcr1) >> 8
- pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pb := (pyy1 + 116130*pcb1) >> 8
- if pr < 0 {
- pr = 0
- } else if pr > 0xffff {
- pr = 0xffff
- }
- if pg < 0 {
- pg = 0
- } else if pg > 0xffff {
- pg = 0xffff
- }
- if pb < 0 {
- pb = 0
- } else if pb > 0xffff {
- pb = 0xffff
- }
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (nnInterpolator) scale_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) {
- dw2 := uint64(dr.Dx()) * 2
- dh2 := uint64(dr.Dy()) * 2
- sw := uint64(sr.Dx())
- sh := uint64(sr.Dy())
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (2*uint64(dy) + 1) * sh / dh2
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (2*uint64(dx) + 1) * sw / dw2
- pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
- pj := ((sr.Min.Y+int(sy))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx))/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10101
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pr := (pyy1 + 91881*pcr1) >> 8
- pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pb := (pyy1 + 116130*pcb1) >> 8
- if pr < 0 {
- pr = 0
- } else if pr > 0xffff {
- pr = 0xffff
- }
- if pg < 0 {
- pg = 0
- } else if pg > 0xffff {
- pg = 0xffff
- }
- if pb < 0 {
- pb = 0
- } else if pb > 0xffff {
- pb = 0xffff
- }
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (nnInterpolator) scale_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) {
- dw2 := uint64(dr.Dx()) * 2
- dh2 := uint64(dr.Dy()) * 2
- sw := uint64(sr.Dx())
- sh := uint64(sr.Dy())
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (2*uint64(dy) + 1) * sh / dh2
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (2*uint64(dx) + 1) * sw / dw2
- pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
- pj := ((sr.Min.Y+int(sy))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10101
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pr := (pyy1 + 91881*pcr1) >> 8
- pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pb := (pyy1 + 116130*pcb1) >> 8
- if pr < 0 {
- pr = 0
- } else if pr > 0xffff {
- pr = 0xffff
- }
- if pg < 0 {
- pg = 0
- } else if pg > 0xffff {
- pg = 0xffff
- }
- if pb < 0 {
- pb = 0
- } else if pb > 0xffff {
- pb = 0xffff
- }
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (nnInterpolator) scale_RGBA_Image_Over(dst *image.RGBA, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) {
- dw2 := uint64(dr.Dx()) * 2
- dh2 := uint64(dr.Dy()) * 2
- sw := uint64(sr.Dx())
- sh := uint64(sr.Dy())
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (2*uint64(dy) + 1) * sh / dh2
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (2*uint64(dx) + 1) * sw / dw2
- pr, pg, pb, pa := src.At(sr.Min.X+int(sx), sr.Min.Y+int(sy)).RGBA()
- pa1 := (0xffff - pa) * 0x101
- dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
- dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
- dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
- dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
- }
- }
-}
-
-func (nnInterpolator) scale_RGBA_Image_Src(dst *image.RGBA, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) {
- dw2 := uint64(dr.Dx()) * 2
- dh2 := uint64(dr.Dy()) * 2
- sw := uint64(sr.Dx())
- sh := uint64(sr.Dy())
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (2*uint64(dy) + 1) * sh / dh2
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (2*uint64(dx) + 1) * sw / dw2
- pr, pg, pb, pa := src.At(sr.Min.X+int(sx), sr.Min.Y+int(sy)).RGBA()
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = uint8(pa >> 8)
- }
- }
-}
-
-func (nnInterpolator) scale_Image_Image_Over(dst Image, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) {
- dw2 := uint64(dr.Dx()) * 2
- dh2 := uint64(dr.Dy()) * 2
- sw := uint64(sr.Dx())
- sh := uint64(sr.Dy())
- srcMask, smp := opts.SrcMask, opts.SrcMaskP
- dstMask, dmp := opts.DstMask, opts.DstMaskP
- dstColorRGBA64 := &color.RGBA64{}
- dstColor := color.Color(dstColorRGBA64)
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (2*uint64(dy) + 1) * sh / dh2
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
- sx := (2*uint64(dx) + 1) * sw / dw2
- pr, pg, pb, pa := src.At(sr.Min.X+int(sx), sr.Min.Y+int(sy)).RGBA()
- if srcMask != nil {
- _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx), smp.Y+sr.Min.Y+int(sy)).RGBA()
- pr = pr * ma / 0xffff
- pg = pg * ma / 0xffff
- pb = pb * ma / 0xffff
- pa = pa * ma / 0xffff
- }
- qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
- if dstMask != nil {
- _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
- pr = pr * ma / 0xffff
- pg = pg * ma / 0xffff
- pb = pb * ma / 0xffff
- pa = pa * ma / 0xffff
- }
- pa1 := 0xffff - pa
- dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
- dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
- dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
- dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
- dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
- }
- }
-}
-
-func (nnInterpolator) scale_Image_Image_Src(dst Image, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) {
- dw2 := uint64(dr.Dx()) * 2
- dh2 := uint64(dr.Dy()) * 2
- sw := uint64(sr.Dx())
- sh := uint64(sr.Dy())
- srcMask, smp := opts.SrcMask, opts.SrcMaskP
- dstMask, dmp := opts.DstMask, opts.DstMaskP
- dstColorRGBA64 := &color.RGBA64{}
- dstColor := color.Color(dstColorRGBA64)
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (2*uint64(dy) + 1) * sh / dh2
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
- sx := (2*uint64(dx) + 1) * sw / dw2
- pr, pg, pb, pa := src.At(sr.Min.X+int(sx), sr.Min.Y+int(sy)).RGBA()
- if srcMask != nil {
- _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx), smp.Y+sr.Min.Y+int(sy)).RGBA()
- pr = pr * ma / 0xffff
- pg = pg * ma / 0xffff
- pb = pb * ma / 0xffff
- pa = pa * ma / 0xffff
- }
- if dstMask != nil {
- qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
- _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
- pr = pr * ma / 0xffff
- pg = pg * ma / 0xffff
- pb = pb * ma / 0xffff
- pa = pa * ma / 0xffff
- pa1 := 0xffff - ma
- dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
- dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
- dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
- dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
- dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
- } else {
- dstColorRGBA64.R = uint16(pr)
- dstColorRGBA64.G = uint16(pg)
- dstColorRGBA64.B = uint16(pb)
- dstColorRGBA64.A = uint16(pa)
- dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
- }
- }
- }
-}
-
-func (nnInterpolator) transform_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.Gray, sr image.Rectangle, bias image.Point, opts *Options) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
- sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
- if !(image.Point{sx0, sy0}).In(sr) {
- continue
- }
- pi := (sy0-src.Rect.Min.Y)*src.Stride + (sx0 - src.Rect.Min.X)
- pr := uint32(src.Pix[pi]) * 0x101
- out := uint8(pr >> 8)
- dst.Pix[d+0] = out
- dst.Pix[d+1] = out
- dst.Pix[d+2] = out
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (nnInterpolator) transform_RGBA_NRGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.NRGBA, sr image.Rectangle, bias image.Point, opts *Options) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
- sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
- if !(image.Point{sx0, sy0}).In(sr) {
- continue
- }
- pi := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
- pa := uint32(src.Pix[pi+3]) * 0x101
- pr := uint32(src.Pix[pi+0]) * pa / 0xff
- pg := uint32(src.Pix[pi+1]) * pa / 0xff
- pb := uint32(src.Pix[pi+2]) * pa / 0xff
- pa1 := (0xffff - pa) * 0x101
- dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
- dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
- dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
- dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
- }
- }
-}
-
-func (nnInterpolator) transform_RGBA_NRGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.NRGBA, sr image.Rectangle, bias image.Point, opts *Options) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
- sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
- if !(image.Point{sx0, sy0}).In(sr) {
- continue
- }
- pi := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
- pa := uint32(src.Pix[pi+3]) * 0x101
- pr := uint32(src.Pix[pi+0]) * pa / 0xff
- pg := uint32(src.Pix[pi+1]) * pa / 0xff
- pb := uint32(src.Pix[pi+2]) * pa / 0xff
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = uint8(pa >> 8)
- }
- }
-}
-
-func (nnInterpolator) transform_RGBA_RGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.RGBA, sr image.Rectangle, bias image.Point, opts *Options) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
- sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
- if !(image.Point{sx0, sy0}).In(sr) {
- continue
- }
- pi := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
- pr := uint32(src.Pix[pi+0]) * 0x101
- pg := uint32(src.Pix[pi+1]) * 0x101
- pb := uint32(src.Pix[pi+2]) * 0x101
- pa := uint32(src.Pix[pi+3]) * 0x101
- pa1 := (0xffff - pa) * 0x101
- dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
- dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
- dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
- dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
- }
- }
-}
-
-func (nnInterpolator) transform_RGBA_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.RGBA, sr image.Rectangle, bias image.Point, opts *Options) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
- sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
- if !(image.Point{sx0, sy0}).In(sr) {
- continue
- }
- pi := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
- pr := uint32(src.Pix[pi+0]) * 0x101
- pg := uint32(src.Pix[pi+1]) * 0x101
- pb := uint32(src.Pix[pi+2]) * 0x101
- pa := uint32(src.Pix[pi+3]) * 0x101
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = uint8(pa >> 8)
- }
- }
-}
-
-func (nnInterpolator) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, opts *Options) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
- sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
- if !(image.Point{sx0, sy0}).In(sr) {
- continue
- }
- pi := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- pj := (sy0-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10101
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pr := (pyy1 + 91881*pcr1) >> 8
- pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pb := (pyy1 + 116130*pcb1) >> 8
- if pr < 0 {
- pr = 0
- } else if pr > 0xffff {
- pr = 0xffff
- }
- if pg < 0 {
- pg = 0
- } else if pg > 0xffff {
- pg = 0xffff
- }
- if pb < 0 {
- pb = 0
- } else if pb > 0xffff {
- pb = 0xffff
- }
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (nnInterpolator) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, opts *Options) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
- sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
- if !(image.Point{sx0, sy0}).In(sr) {
- continue
- }
- pi := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- pj := (sy0-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10101
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pr := (pyy1 + 91881*pcr1) >> 8
- pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pb := (pyy1 + 116130*pcb1) >> 8
- if pr < 0 {
- pr = 0
- } else if pr > 0xffff {
- pr = 0xffff
- }
- if pg < 0 {
- pg = 0
- } else if pg > 0xffff {
- pg = 0xffff
- }
- if pb < 0 {
- pb = 0
- } else if pb > 0xffff {
- pb = 0xffff
- }
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (nnInterpolator) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, opts *Options) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
- sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
- if !(image.Point{sx0, sy0}).In(sr) {
- continue
- }
- pi := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- pj := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10101
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pr := (pyy1 + 91881*pcr1) >> 8
- pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pb := (pyy1 + 116130*pcb1) >> 8
- if pr < 0 {
- pr = 0
- } else if pr > 0xffff {
- pr = 0xffff
- }
- if pg < 0 {
- pg = 0
- } else if pg > 0xffff {
- pg = 0xffff
- }
- if pb < 0 {
- pb = 0
- } else if pb > 0xffff {
- pb = 0xffff
- }
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (nnInterpolator) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, opts *Options) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
- sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
- if !(image.Point{sx0, sy0}).In(sr) {
- continue
- }
- pi := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- pj := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10101
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pr := (pyy1 + 91881*pcr1) >> 8
- pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pb := (pyy1 + 116130*pcb1) >> 8
- if pr < 0 {
- pr = 0
- } else if pr > 0xffff {
- pr = 0xffff
- }
- if pg < 0 {
- pg = 0
- } else if pg > 0xffff {
- pg = 0xffff
- }
- if pb < 0 {
- pb = 0
- } else if pb > 0xffff {
- pb = 0xffff
- }
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (nnInterpolator) transform_RGBA_Image_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
- sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
- if !(image.Point{sx0, sy0}).In(sr) {
- continue
- }
- pr, pg, pb, pa := src.At(sx0, sy0).RGBA()
- pa1 := (0xffff - pa) * 0x101
- dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
- dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
- dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
- dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
- }
- }
-}
-
-func (nnInterpolator) transform_RGBA_Image_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
- sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
- if !(image.Point{sx0, sy0}).In(sr) {
- continue
- }
- pr, pg, pb, pa := src.At(sx0, sy0).RGBA()
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = uint8(pa >> 8)
- }
- }
-}
-
-func (nnInterpolator) transform_Image_Image_Over(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
- srcMask, smp := opts.SrcMask, opts.SrcMaskP
- dstMask, dmp := opts.DstMask, opts.DstMaskP
- dstColorRGBA64 := &color.RGBA64{}
- dstColor := color.Color(dstColorRGBA64)
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
- sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
- if !(image.Point{sx0, sy0}).In(sr) {
- continue
- }
- pr, pg, pb, pa := src.At(sx0, sy0).RGBA()
- if srcMask != nil {
- _, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy0).RGBA()
- pr = pr * ma / 0xffff
- pg = pg * ma / 0xffff
- pb = pb * ma / 0xffff
- pa = pa * ma / 0xffff
- }
- qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
- if dstMask != nil {
- _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
- pr = pr * ma / 0xffff
- pg = pg * ma / 0xffff
- pb = pb * ma / 0xffff
- pa = pa * ma / 0xffff
- }
- pa1 := 0xffff - pa
- dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
- dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
- dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
- dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
- dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
- }
- }
-}
-
-func (nnInterpolator) transform_Image_Image_Src(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
- srcMask, smp := opts.SrcMask, opts.SrcMaskP
- dstMask, dmp := opts.DstMask, opts.DstMaskP
- dstColorRGBA64 := &color.RGBA64{}
- dstColor := color.Color(dstColorRGBA64)
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
- sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
- if !(image.Point{sx0, sy0}).In(sr) {
- continue
- }
- pr, pg, pb, pa := src.At(sx0, sy0).RGBA()
- if srcMask != nil {
- _, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy0).RGBA()
- pr = pr * ma / 0xffff
- pg = pg * ma / 0xffff
- pb = pb * ma / 0xffff
- pa = pa * ma / 0xffff
- }
- if dstMask != nil {
- qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
- _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
- pr = pr * ma / 0xffff
- pg = pg * ma / 0xffff
- pb = pb * ma / 0xffff
- pa = pa * ma / 0xffff
- pa1 := 0xffff - ma
- dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
- dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
- dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
- dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
- dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
- } else {
- dstColorRGBA64.R = uint16(pr)
- dstColorRGBA64.G = uint16(pg)
- dstColorRGBA64.B = uint16(pb)
- dstColorRGBA64.A = uint16(pa)
- dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
- }
- }
- }
-}
-
-func (z ablInterpolator) Scale(dst Image, dr image.Rectangle, src image.Image, sr image.Rectangle, op Op, opts *Options) {
- // Try to simplify a Scale to a Copy when DstMask is not specified.
- // If DstMask is not nil, Copy will call Scale back with same dr and sr, and cause stack overflow.
- if dr.Size() == sr.Size() && (opts == nil || opts.DstMask == nil) {
- Copy(dst, dr.Min, src, sr, op, opts)
- return
- }
-
- var o Options
- if opts != nil {
- o = *opts
- }
-
- // adr is the affected destination pixels.
- adr := dst.Bounds().Intersect(dr)
- adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
- if adr.Empty() || sr.Empty() {
- return
- }
- // Make adr relative to dr.Min.
- adr = adr.Sub(dr.Min)
- if op == Over && o.SrcMask == nil && opaque(src) {
- op = Src
- }
-
- // sr is the source pixels. If it extends beyond the src bounds,
- // we cannot use the type-specific fast paths, as they access
- // the Pix fields directly without bounds checking.
- //
- // Similarly, the fast paths assume that the masks are nil.
- if o.DstMask != nil || o.SrcMask != nil || !sr.In(src.Bounds()) {
- switch op {
- case Over:
- z.scale_Image_Image_Over(dst, dr, adr, src, sr, &o)
- case Src:
- z.scale_Image_Image_Src(dst, dr, adr, src, sr, &o)
- }
- } else if _, ok := src.(*image.Uniform); ok {
- Draw(dst, dr, src, src.Bounds().Min, op)
- } else {
- switch op {
- case Over:
- switch dst := dst.(type) {
- case *image.RGBA:
- switch src := src.(type) {
- case *image.NRGBA:
- z.scale_RGBA_NRGBA_Over(dst, dr, adr, src, sr, &o)
- case *image.RGBA:
- z.scale_RGBA_RGBA_Over(dst, dr, adr, src, sr, &o)
- default:
- z.scale_RGBA_Image_Over(dst, dr, adr, src, sr, &o)
- }
- default:
- switch src := src.(type) {
- default:
- z.scale_Image_Image_Over(dst, dr, adr, src, sr, &o)
- }
- }
- case Src:
- switch dst := dst.(type) {
- case *image.RGBA:
- switch src := src.(type) {
- case *image.Gray:
- z.scale_RGBA_Gray_Src(dst, dr, adr, src, sr, &o)
- case *image.NRGBA:
- z.scale_RGBA_NRGBA_Src(dst, dr, adr, src, sr, &o)
- case *image.RGBA:
- z.scale_RGBA_RGBA_Src(dst, dr, adr, src, sr, &o)
- case *image.YCbCr:
- switch src.SubsampleRatio {
- default:
- z.scale_RGBA_Image_Src(dst, dr, adr, src, sr, &o)
- case image.YCbCrSubsampleRatio444:
- z.scale_RGBA_YCbCr444_Src(dst, dr, adr, src, sr, &o)
- case image.YCbCrSubsampleRatio422:
- z.scale_RGBA_YCbCr422_Src(dst, dr, adr, src, sr, &o)
- case image.YCbCrSubsampleRatio420:
- z.scale_RGBA_YCbCr420_Src(dst, dr, adr, src, sr, &o)
- case image.YCbCrSubsampleRatio440:
- z.scale_RGBA_YCbCr440_Src(dst, dr, adr, src, sr, &o)
- }
- default:
- z.scale_RGBA_Image_Src(dst, dr, adr, src, sr, &o)
- }
- default:
- switch src := src.(type) {
- default:
- z.scale_Image_Image_Src(dst, dr, adr, src, sr, &o)
- }
- }
- }
- }
-}
-
-func (z ablInterpolator) Transform(dst Image, s2d f64.Aff3, src image.Image, sr image.Rectangle, op Op, opts *Options) {
- // Try to simplify a Transform to a Copy.
- if s2d[0] == 1 && s2d[1] == 0 && s2d[3] == 0 && s2d[4] == 1 {
- dx := int(s2d[2])
- dy := int(s2d[5])
- if float64(dx) == s2d[2] && float64(dy) == s2d[5] {
- Copy(dst, image.Point{X: sr.Min.X + dx, Y: sr.Min.X + dy}, src, sr, op, opts)
- return
- }
- }
-
- var o Options
- if opts != nil {
- o = *opts
- }
-
- dr := transformRect(&s2d, &sr)
- // adr is the affected destination pixels.
- adr := dst.Bounds().Intersect(dr)
- adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
- if adr.Empty() || sr.Empty() {
- return
- }
- if op == Over && o.SrcMask == nil && opaque(src) {
- op = Src
- }
-
- d2s := invert(&s2d)
- // bias is a translation of the mapping from dst coordinates to src
- // coordinates such that the latter temporarily have non-negative X
- // and Y coordinates. This allows us to write int(f) instead of
- // int(math.Floor(f)), since "round to zero" and "round down" are
- // equivalent when f >= 0, but the former is much cheaper. The X--
- // and Y-- are because the TransformLeaf methods have a "sx -= 0.5"
- // adjustment.
- bias := transformRect(&d2s, &adr).Min
- bias.X--
- bias.Y--
- d2s[2] -= float64(bias.X)
- d2s[5] -= float64(bias.Y)
- // Make adr relative to dr.Min.
- adr = adr.Sub(dr.Min)
- // sr is the source pixels. If it extends beyond the src bounds,
- // we cannot use the type-specific fast paths, as they access
- // the Pix fields directly without bounds checking.
- //
- // Similarly, the fast paths assume that the masks are nil.
- if o.DstMask != nil || o.SrcMask != nil || !sr.In(src.Bounds()) {
- switch op {
- case Over:
- z.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
- case Src:
- z.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
- }
- } else if u, ok := src.(*image.Uniform); ok {
- transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, op)
- } else {
- switch op {
- case Over:
- switch dst := dst.(type) {
- case *image.RGBA:
- switch src := src.(type) {
- case *image.NRGBA:
- z.transform_RGBA_NRGBA_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
- case *image.RGBA:
- z.transform_RGBA_RGBA_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
- default:
- z.transform_RGBA_Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
- }
- default:
- switch src := src.(type) {
- default:
- z.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
- }
- }
- case Src:
- switch dst := dst.(type) {
- case *image.RGBA:
- switch src := src.(type) {
- case *image.Gray:
- z.transform_RGBA_Gray_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
- case *image.NRGBA:
- z.transform_RGBA_NRGBA_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
- case *image.RGBA:
- z.transform_RGBA_RGBA_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
- case *image.YCbCr:
- switch src.SubsampleRatio {
- default:
- z.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
- case image.YCbCrSubsampleRatio444:
- z.transform_RGBA_YCbCr444_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
- case image.YCbCrSubsampleRatio422:
- z.transform_RGBA_YCbCr422_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
- case image.YCbCrSubsampleRatio420:
- z.transform_RGBA_YCbCr420_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
- case image.YCbCrSubsampleRatio440:
- z.transform_RGBA_YCbCr440_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
- }
- default:
- z.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
- }
- default:
- switch src := src.(type) {
- default:
- z.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
- }
- }
- }
- }
-}
-
-func (ablInterpolator) scale_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.Gray, sr image.Rectangle, opts *Options) {
- sw := int32(sr.Dx())
- sh := int32(sr.Dy())
- yscale := float64(sh) / float64(dr.Dy())
- xscale := float64(sw) / float64(dr.Dx())
- swMinus1, shMinus1 := sw-1, sh-1
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (float64(dy)+0.5)*yscale - 0.5
- // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
- // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
- // sx, below.
- sy0 := int32(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy1 := sy0 + 1
- if sy < 0 {
- sy0, sy1 = 0, 0
- yFrac0, yFrac1 = 0, 1
- } else if sy1 > shMinus1 {
- sy0, sy1 = shMinus1, shMinus1
- yFrac0, yFrac1 = 1, 0
- }
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
-
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (float64(dx)+0.5)*xscale - 0.5
- sx0 := int32(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx1 := sx0 + 1
- if sx < 0 {
- sx0, sx1 = 0, 0
- xFrac0, xFrac1 = 0, 1
- } else if sx1 > swMinus1 {
- sx0, sx1 = swMinus1, swMinus1
- xFrac0, xFrac1 = 1, 0
- }
-
- s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
- s00ru := uint32(src.Pix[s00i]) * 0x101
- s00r := float64(s00ru)
- s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
- s10ru := uint32(src.Pix[s10i]) * 0x101
- s10r := float64(s10ru)
- s10r = xFrac1*s00r + xFrac0*s10r
- s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
- s01ru := uint32(src.Pix[s01i]) * 0x101
- s01r := float64(s01ru)
- s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
- s11ru := uint32(src.Pix[s11i]) * 0x101
- s11r := float64(s11ru)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11r = yFrac1*s10r + yFrac0*s11r
- pr := uint32(s11r)
- out := uint8(pr >> 8)
- dst.Pix[d+0] = out
- dst.Pix[d+1] = out
- dst.Pix[d+2] = out
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (ablInterpolator) scale_RGBA_NRGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, src *image.NRGBA, sr image.Rectangle, opts *Options) {
- sw := int32(sr.Dx())
- sh := int32(sr.Dy())
- yscale := float64(sh) / float64(dr.Dy())
- xscale := float64(sw) / float64(dr.Dx())
- swMinus1, shMinus1 := sw-1, sh-1
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (float64(dy)+0.5)*yscale - 0.5
- // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
- // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
- // sx, below.
- sy0 := int32(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy1 := sy0 + 1
- if sy < 0 {
- sy0, sy1 = 0, 0
- yFrac0, yFrac1 = 0, 1
- } else if sy1 > shMinus1 {
- sy0, sy1 = shMinus1, shMinus1
- yFrac0, yFrac1 = 1, 0
- }
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
-
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (float64(dx)+0.5)*xscale - 0.5
- sx0 := int32(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx1 := sx0 + 1
- if sx < 0 {
- sx0, sx1 = 0, 0
- xFrac0, xFrac1 = 0, 1
- } else if sx1 > swMinus1 {
- sx0, sx1 = swMinus1, swMinus1
- xFrac0, xFrac1 = 1, 0
- }
-
- s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4
- s00au := uint32(src.Pix[s00i+3]) * 0x101
- s00ru := uint32(src.Pix[s00i+0]) * s00au / 0xff
- s00gu := uint32(src.Pix[s00i+1]) * s00au / 0xff
- s00bu := uint32(src.Pix[s00i+2]) * s00au / 0xff
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s00a := float64(s00au)
- s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4
- s10au := uint32(src.Pix[s10i+3]) * 0x101
- s10ru := uint32(src.Pix[s10i+0]) * s10au / 0xff
- s10gu := uint32(src.Pix[s10i+1]) * s10au / 0xff
- s10bu := uint32(src.Pix[s10i+2]) * s10au / 0xff
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10a := float64(s10au)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s10a = xFrac1*s00a + xFrac0*s10a
- s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4
- s01au := uint32(src.Pix[s01i+3]) * 0x101
- s01ru := uint32(src.Pix[s01i+0]) * s01au / 0xff
- s01gu := uint32(src.Pix[s01i+1]) * s01au / 0xff
- s01bu := uint32(src.Pix[s01i+2]) * s01au / 0xff
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s01a := float64(s01au)
- s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4
- s11au := uint32(src.Pix[s11i+3]) * 0x101
- s11ru := uint32(src.Pix[s11i+0]) * s11au / 0xff
- s11gu := uint32(src.Pix[s11i+1]) * s11au / 0xff
- s11bu := uint32(src.Pix[s11i+2]) * s11au / 0xff
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11a := float64(s11au)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11a = xFrac1*s01a + xFrac0*s11a
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- s11a = yFrac1*s10a + yFrac0*s11a
- pr := uint32(s11r)
- pg := uint32(s11g)
- pb := uint32(s11b)
- pa := uint32(s11a)
- pa1 := (0xffff - pa) * 0x101
- dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
- dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
- dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
- dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
- }
- }
-}
-
-func (ablInterpolator) scale_RGBA_NRGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.NRGBA, sr image.Rectangle, opts *Options) {
- sw := int32(sr.Dx())
- sh := int32(sr.Dy())
- yscale := float64(sh) / float64(dr.Dy())
- xscale := float64(sw) / float64(dr.Dx())
- swMinus1, shMinus1 := sw-1, sh-1
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (float64(dy)+0.5)*yscale - 0.5
- // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
- // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
- // sx, below.
- sy0 := int32(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy1 := sy0 + 1
- if sy < 0 {
- sy0, sy1 = 0, 0
- yFrac0, yFrac1 = 0, 1
- } else if sy1 > shMinus1 {
- sy0, sy1 = shMinus1, shMinus1
- yFrac0, yFrac1 = 1, 0
- }
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
-
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (float64(dx)+0.5)*xscale - 0.5
- sx0 := int32(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx1 := sx0 + 1
- if sx < 0 {
- sx0, sx1 = 0, 0
- xFrac0, xFrac1 = 0, 1
- } else if sx1 > swMinus1 {
- sx0, sx1 = swMinus1, swMinus1
- xFrac0, xFrac1 = 1, 0
- }
-
- s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4
- s00au := uint32(src.Pix[s00i+3]) * 0x101
- s00ru := uint32(src.Pix[s00i+0]) * s00au / 0xff
- s00gu := uint32(src.Pix[s00i+1]) * s00au / 0xff
- s00bu := uint32(src.Pix[s00i+2]) * s00au / 0xff
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s00a := float64(s00au)
- s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4
- s10au := uint32(src.Pix[s10i+3]) * 0x101
- s10ru := uint32(src.Pix[s10i+0]) * s10au / 0xff
- s10gu := uint32(src.Pix[s10i+1]) * s10au / 0xff
- s10bu := uint32(src.Pix[s10i+2]) * s10au / 0xff
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10a := float64(s10au)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s10a = xFrac1*s00a + xFrac0*s10a
- s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4
- s01au := uint32(src.Pix[s01i+3]) * 0x101
- s01ru := uint32(src.Pix[s01i+0]) * s01au / 0xff
- s01gu := uint32(src.Pix[s01i+1]) * s01au / 0xff
- s01bu := uint32(src.Pix[s01i+2]) * s01au / 0xff
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s01a := float64(s01au)
- s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4
- s11au := uint32(src.Pix[s11i+3]) * 0x101
- s11ru := uint32(src.Pix[s11i+0]) * s11au / 0xff
- s11gu := uint32(src.Pix[s11i+1]) * s11au / 0xff
- s11bu := uint32(src.Pix[s11i+2]) * s11au / 0xff
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11a := float64(s11au)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11a = xFrac1*s01a + xFrac0*s11a
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- s11a = yFrac1*s10a + yFrac0*s11a
- pr := uint32(s11r)
- pg := uint32(s11g)
- pb := uint32(s11b)
- pa := uint32(s11a)
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = uint8(pa >> 8)
- }
- }
-}
-
-func (ablInterpolator) scale_RGBA_RGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, src *image.RGBA, sr image.Rectangle, opts *Options) {
- sw := int32(sr.Dx())
- sh := int32(sr.Dy())
- yscale := float64(sh) / float64(dr.Dy())
- xscale := float64(sw) / float64(dr.Dx())
- swMinus1, shMinus1 := sw-1, sh-1
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (float64(dy)+0.5)*yscale - 0.5
- // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
- // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
- // sx, below.
- sy0 := int32(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy1 := sy0 + 1
- if sy < 0 {
- sy0, sy1 = 0, 0
- yFrac0, yFrac1 = 0, 1
- } else if sy1 > shMinus1 {
- sy0, sy1 = shMinus1, shMinus1
- yFrac0, yFrac1 = 1, 0
- }
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
-
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (float64(dx)+0.5)*xscale - 0.5
- sx0 := int32(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx1 := sx0 + 1
- if sx < 0 {
- sx0, sx1 = 0, 0
- xFrac0, xFrac1 = 0, 1
- } else if sx1 > swMinus1 {
- sx0, sx1 = swMinus1, swMinus1
- xFrac0, xFrac1 = 1, 0
- }
-
- s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4
- s00ru := uint32(src.Pix[s00i+0]) * 0x101
- s00gu := uint32(src.Pix[s00i+1]) * 0x101
- s00bu := uint32(src.Pix[s00i+2]) * 0x101
- s00au := uint32(src.Pix[s00i+3]) * 0x101
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s00a := float64(s00au)
- s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4
- s10ru := uint32(src.Pix[s10i+0]) * 0x101
- s10gu := uint32(src.Pix[s10i+1]) * 0x101
- s10bu := uint32(src.Pix[s10i+2]) * 0x101
- s10au := uint32(src.Pix[s10i+3]) * 0x101
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10a := float64(s10au)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s10a = xFrac1*s00a + xFrac0*s10a
- s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4
- s01ru := uint32(src.Pix[s01i+0]) * 0x101
- s01gu := uint32(src.Pix[s01i+1]) * 0x101
- s01bu := uint32(src.Pix[s01i+2]) * 0x101
- s01au := uint32(src.Pix[s01i+3]) * 0x101
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s01a := float64(s01au)
- s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4
- s11ru := uint32(src.Pix[s11i+0]) * 0x101
- s11gu := uint32(src.Pix[s11i+1]) * 0x101
- s11bu := uint32(src.Pix[s11i+2]) * 0x101
- s11au := uint32(src.Pix[s11i+3]) * 0x101
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11a := float64(s11au)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11a = xFrac1*s01a + xFrac0*s11a
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- s11a = yFrac1*s10a + yFrac0*s11a
- pr := uint32(s11r)
- pg := uint32(s11g)
- pb := uint32(s11b)
- pa := uint32(s11a)
- pa1 := (0xffff - pa) * 0x101
- dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
- dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
- dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
- dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
- }
- }
-}
-
-func (ablInterpolator) scale_RGBA_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.RGBA, sr image.Rectangle, opts *Options) {
- sw := int32(sr.Dx())
- sh := int32(sr.Dy())
- yscale := float64(sh) / float64(dr.Dy())
- xscale := float64(sw) / float64(dr.Dx())
- swMinus1, shMinus1 := sw-1, sh-1
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (float64(dy)+0.5)*yscale - 0.5
- // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
- // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
- // sx, below.
- sy0 := int32(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy1 := sy0 + 1
- if sy < 0 {
- sy0, sy1 = 0, 0
- yFrac0, yFrac1 = 0, 1
- } else if sy1 > shMinus1 {
- sy0, sy1 = shMinus1, shMinus1
- yFrac0, yFrac1 = 1, 0
- }
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
-
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (float64(dx)+0.5)*xscale - 0.5
- sx0 := int32(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx1 := sx0 + 1
- if sx < 0 {
- sx0, sx1 = 0, 0
- xFrac0, xFrac1 = 0, 1
- } else if sx1 > swMinus1 {
- sx0, sx1 = swMinus1, swMinus1
- xFrac0, xFrac1 = 1, 0
- }
-
- s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4
- s00ru := uint32(src.Pix[s00i+0]) * 0x101
- s00gu := uint32(src.Pix[s00i+1]) * 0x101
- s00bu := uint32(src.Pix[s00i+2]) * 0x101
- s00au := uint32(src.Pix[s00i+3]) * 0x101
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s00a := float64(s00au)
- s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4
- s10ru := uint32(src.Pix[s10i+0]) * 0x101
- s10gu := uint32(src.Pix[s10i+1]) * 0x101
- s10bu := uint32(src.Pix[s10i+2]) * 0x101
- s10au := uint32(src.Pix[s10i+3]) * 0x101
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10a := float64(s10au)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s10a = xFrac1*s00a + xFrac0*s10a
- s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4
- s01ru := uint32(src.Pix[s01i+0]) * 0x101
- s01gu := uint32(src.Pix[s01i+1]) * 0x101
- s01bu := uint32(src.Pix[s01i+2]) * 0x101
- s01au := uint32(src.Pix[s01i+3]) * 0x101
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s01a := float64(s01au)
- s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4
- s11ru := uint32(src.Pix[s11i+0]) * 0x101
- s11gu := uint32(src.Pix[s11i+1]) * 0x101
- s11bu := uint32(src.Pix[s11i+2]) * 0x101
- s11au := uint32(src.Pix[s11i+3]) * 0x101
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11a := float64(s11au)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11a = xFrac1*s01a + xFrac0*s11a
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- s11a = yFrac1*s10a + yFrac0*s11a
- pr := uint32(s11r)
- pg := uint32(s11g)
- pb := uint32(s11b)
- pa := uint32(s11a)
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = uint8(pa >> 8)
- }
- }
-}
-
-func (ablInterpolator) scale_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) {
- sw := int32(sr.Dx())
- sh := int32(sr.Dy())
- yscale := float64(sh) / float64(dr.Dy())
- xscale := float64(sw) / float64(dr.Dx())
- swMinus1, shMinus1 := sw-1, sh-1
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (float64(dy)+0.5)*yscale - 0.5
- // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
- // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
- // sx, below.
- sy0 := int32(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy1 := sy0 + 1
- if sy < 0 {
- sy0, sy1 = 0, 0
- yFrac0, yFrac1 = 0, 1
- } else if sy1 > shMinus1 {
- sy0, sy1 = shMinus1, shMinus1
- yFrac0, yFrac1 = 1, 0
- }
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
-
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (float64(dx)+0.5)*xscale - 0.5
- sx0 := int32(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx1 := sx0 + 1
- if sx < 0 {
- sx0, sx1 = 0, 0
- xFrac0, xFrac1 = 0, 1
- } else if sx1 > swMinus1 {
- sx0, sx1 = swMinus1, swMinus1
- xFrac0, xFrac1 = 1, 0
- }
-
- s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
- s00j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i]) * 0x10101
- s00cb1 := int(src.Cb[s00j]) - 128
- s00cr1 := int(src.Cr[s00j]) - 128
- s00ru := (s00yy1 + 91881*s00cr1) >> 8
- s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
- s00bu := (s00yy1 + 116130*s00cb1) >> 8
- if s00ru < 0 {
- s00ru = 0
- } else if s00ru > 0xffff {
- s00ru = 0xffff
- }
- if s00gu < 0 {
- s00gu = 0
- } else if s00gu > 0xffff {
- s00gu = 0xffff
- }
- if s00bu < 0 {
- s00bu = 0
- } else if s00bu > 0xffff {
- s00bu = 0xffff
- }
-
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
- s10j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i]) * 0x10101
- s10cb1 := int(src.Cb[s10j]) - 128
- s10cr1 := int(src.Cr[s10j]) - 128
- s10ru := (s10yy1 + 91881*s10cr1) >> 8
- s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
- s10bu := (s10yy1 + 116130*s10cb1) >> 8
- if s10ru < 0 {
- s10ru = 0
- } else if s10ru > 0xffff {
- s10ru = 0xffff
- }
- if s10gu < 0 {
- s10gu = 0
- } else if s10gu > 0xffff {
- s10gu = 0xffff
- }
- if s10bu < 0 {
- s10bu = 0
- } else if s10bu > 0xffff {
- s10bu = 0xffff
- }
-
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
- s01j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i]) * 0x10101
- s01cb1 := int(src.Cb[s01j]) - 128
- s01cr1 := int(src.Cr[s01j]) - 128
- s01ru := (s01yy1 + 91881*s01cr1) >> 8
- s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
- s01bu := (s01yy1 + 116130*s01cb1) >> 8
- if s01ru < 0 {
- s01ru = 0
- } else if s01ru > 0xffff {
- s01ru = 0xffff
- }
- if s01gu < 0 {
- s01gu = 0
- } else if s01gu > 0xffff {
- s01gu = 0xffff
- }
- if s01bu < 0 {
- s01bu = 0
- } else if s01bu > 0xffff {
- s01bu = 0xffff
- }
-
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
- s11j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i]) * 0x10101
- s11cb1 := int(src.Cb[s11j]) - 128
- s11cr1 := int(src.Cr[s11j]) - 128
- s11ru := (s11yy1 + 91881*s11cr1) >> 8
- s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
- s11bu := (s11yy1 + 116130*s11cb1) >> 8
- if s11ru < 0 {
- s11ru = 0
- } else if s11ru > 0xffff {
- s11ru = 0xffff
- }
- if s11gu < 0 {
- s11gu = 0
- } else if s11gu > 0xffff {
- s11gu = 0xffff
- }
- if s11bu < 0 {
- s11bu = 0
- } else if s11bu > 0xffff {
- s11bu = 0xffff
- }
-
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- pr := uint32(s11r)
- pg := uint32(s11g)
- pb := uint32(s11b)
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (ablInterpolator) scale_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) {
- sw := int32(sr.Dx())
- sh := int32(sr.Dy())
- yscale := float64(sh) / float64(dr.Dy())
- xscale := float64(sw) / float64(dr.Dx())
- swMinus1, shMinus1 := sw-1, sh-1
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (float64(dy)+0.5)*yscale - 0.5
- // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
- // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
- // sx, below.
- sy0 := int32(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy1 := sy0 + 1
- if sy < 0 {
- sy0, sy1 = 0, 0
- yFrac0, yFrac1 = 0, 1
- } else if sy1 > shMinus1 {
- sy0, sy1 = shMinus1, shMinus1
- yFrac0, yFrac1 = 1, 0
- }
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
-
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (float64(dx)+0.5)*xscale - 0.5
- sx0 := int32(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx1 := sx0 + 1
- if sx < 0 {
- sx0, sx1 = 0, 0
- xFrac0, xFrac1 = 0, 1
- } else if sx1 > swMinus1 {
- sx0, sx1 = swMinus1, swMinus1
- xFrac0, xFrac1 = 1, 0
- }
-
- s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
- s00j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i]) * 0x10101
- s00cb1 := int(src.Cb[s00j]) - 128
- s00cr1 := int(src.Cr[s00j]) - 128
- s00ru := (s00yy1 + 91881*s00cr1) >> 8
- s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
- s00bu := (s00yy1 + 116130*s00cb1) >> 8
- if s00ru < 0 {
- s00ru = 0
- } else if s00ru > 0xffff {
- s00ru = 0xffff
- }
- if s00gu < 0 {
- s00gu = 0
- } else if s00gu > 0xffff {
- s00gu = 0xffff
- }
- if s00bu < 0 {
- s00bu = 0
- } else if s00bu > 0xffff {
- s00bu = 0xffff
- }
-
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
- s10j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i]) * 0x10101
- s10cb1 := int(src.Cb[s10j]) - 128
- s10cr1 := int(src.Cr[s10j]) - 128
- s10ru := (s10yy1 + 91881*s10cr1) >> 8
- s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
- s10bu := (s10yy1 + 116130*s10cb1) >> 8
- if s10ru < 0 {
- s10ru = 0
- } else if s10ru > 0xffff {
- s10ru = 0xffff
- }
- if s10gu < 0 {
- s10gu = 0
- } else if s10gu > 0xffff {
- s10gu = 0xffff
- }
- if s10bu < 0 {
- s10bu = 0
- } else if s10bu > 0xffff {
- s10bu = 0xffff
- }
-
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
- s01j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i]) * 0x10101
- s01cb1 := int(src.Cb[s01j]) - 128
- s01cr1 := int(src.Cr[s01j]) - 128
- s01ru := (s01yy1 + 91881*s01cr1) >> 8
- s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
- s01bu := (s01yy1 + 116130*s01cb1) >> 8
- if s01ru < 0 {
- s01ru = 0
- } else if s01ru > 0xffff {
- s01ru = 0xffff
- }
- if s01gu < 0 {
- s01gu = 0
- } else if s01gu > 0xffff {
- s01gu = 0xffff
- }
- if s01bu < 0 {
- s01bu = 0
- } else if s01bu > 0xffff {
- s01bu = 0xffff
- }
-
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
- s11j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i]) * 0x10101
- s11cb1 := int(src.Cb[s11j]) - 128
- s11cr1 := int(src.Cr[s11j]) - 128
- s11ru := (s11yy1 + 91881*s11cr1) >> 8
- s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
- s11bu := (s11yy1 + 116130*s11cb1) >> 8
- if s11ru < 0 {
- s11ru = 0
- } else if s11ru > 0xffff {
- s11ru = 0xffff
- }
- if s11gu < 0 {
- s11gu = 0
- } else if s11gu > 0xffff {
- s11gu = 0xffff
- }
- if s11bu < 0 {
- s11bu = 0
- } else if s11bu > 0xffff {
- s11bu = 0xffff
- }
-
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- pr := uint32(s11r)
- pg := uint32(s11g)
- pb := uint32(s11b)
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (ablInterpolator) scale_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) {
- sw := int32(sr.Dx())
- sh := int32(sr.Dy())
- yscale := float64(sh) / float64(dr.Dy())
- xscale := float64(sw) / float64(dr.Dx())
- swMinus1, shMinus1 := sw-1, sh-1
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (float64(dy)+0.5)*yscale - 0.5
- // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
- // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
- // sx, below.
- sy0 := int32(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy1 := sy0 + 1
- if sy < 0 {
- sy0, sy1 = 0, 0
- yFrac0, yFrac1 = 0, 1
- } else if sy1 > shMinus1 {
- sy0, sy1 = shMinus1, shMinus1
- yFrac0, yFrac1 = 1, 0
- }
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
-
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (float64(dx)+0.5)*xscale - 0.5
- sx0 := int32(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx1 := sx0 + 1
- if sx < 0 {
- sx0, sx1 = 0, 0
- xFrac0, xFrac1 = 0, 1
- } else if sx1 > swMinus1 {
- sx0, sx1 = swMinus1, swMinus1
- xFrac0, xFrac1 = 1, 0
- }
-
- s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
- s00j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i]) * 0x10101
- s00cb1 := int(src.Cb[s00j]) - 128
- s00cr1 := int(src.Cr[s00j]) - 128
- s00ru := (s00yy1 + 91881*s00cr1) >> 8
- s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
- s00bu := (s00yy1 + 116130*s00cb1) >> 8
- if s00ru < 0 {
- s00ru = 0
- } else if s00ru > 0xffff {
- s00ru = 0xffff
- }
- if s00gu < 0 {
- s00gu = 0
- } else if s00gu > 0xffff {
- s00gu = 0xffff
- }
- if s00bu < 0 {
- s00bu = 0
- } else if s00bu > 0xffff {
- s00bu = 0xffff
- }
-
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
- s10j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i]) * 0x10101
- s10cb1 := int(src.Cb[s10j]) - 128
- s10cr1 := int(src.Cr[s10j]) - 128
- s10ru := (s10yy1 + 91881*s10cr1) >> 8
- s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
- s10bu := (s10yy1 + 116130*s10cb1) >> 8
- if s10ru < 0 {
- s10ru = 0
- } else if s10ru > 0xffff {
- s10ru = 0xffff
- }
- if s10gu < 0 {
- s10gu = 0
- } else if s10gu > 0xffff {
- s10gu = 0xffff
- }
- if s10bu < 0 {
- s10bu = 0
- } else if s10bu > 0xffff {
- s10bu = 0xffff
- }
-
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
- s01j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i]) * 0x10101
- s01cb1 := int(src.Cb[s01j]) - 128
- s01cr1 := int(src.Cr[s01j]) - 128
- s01ru := (s01yy1 + 91881*s01cr1) >> 8
- s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
- s01bu := (s01yy1 + 116130*s01cb1) >> 8
- if s01ru < 0 {
- s01ru = 0
- } else if s01ru > 0xffff {
- s01ru = 0xffff
- }
- if s01gu < 0 {
- s01gu = 0
- } else if s01gu > 0xffff {
- s01gu = 0xffff
- }
- if s01bu < 0 {
- s01bu = 0
- } else if s01bu > 0xffff {
- s01bu = 0xffff
- }
-
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
- s11j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i]) * 0x10101
- s11cb1 := int(src.Cb[s11j]) - 128
- s11cr1 := int(src.Cr[s11j]) - 128
- s11ru := (s11yy1 + 91881*s11cr1) >> 8
- s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
- s11bu := (s11yy1 + 116130*s11cb1) >> 8
- if s11ru < 0 {
- s11ru = 0
- } else if s11ru > 0xffff {
- s11ru = 0xffff
- }
- if s11gu < 0 {
- s11gu = 0
- } else if s11gu > 0xffff {
- s11gu = 0xffff
- }
- if s11bu < 0 {
- s11bu = 0
- } else if s11bu > 0xffff {
- s11bu = 0xffff
- }
-
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- pr := uint32(s11r)
- pg := uint32(s11g)
- pb := uint32(s11b)
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (ablInterpolator) scale_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) {
- sw := int32(sr.Dx())
- sh := int32(sr.Dy())
- yscale := float64(sh) / float64(dr.Dy())
- xscale := float64(sw) / float64(dr.Dx())
- swMinus1, shMinus1 := sw-1, sh-1
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (float64(dy)+0.5)*yscale - 0.5
- // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
- // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
- // sx, below.
- sy0 := int32(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy1 := sy0 + 1
- if sy < 0 {
- sy0, sy1 = 0, 0
- yFrac0, yFrac1 = 0, 1
- } else if sy1 > shMinus1 {
- sy0, sy1 = shMinus1, shMinus1
- yFrac0, yFrac1 = 1, 0
- }
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
-
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (float64(dx)+0.5)*xscale - 0.5
- sx0 := int32(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx1 := sx0 + 1
- if sx < 0 {
- sx0, sx1 = 0, 0
- xFrac0, xFrac1 = 0, 1
- } else if sx1 > swMinus1 {
- sx0, sx1 = swMinus1, swMinus1
- xFrac0, xFrac1 = 1, 0
- }
-
- s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
- s00j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i]) * 0x10101
- s00cb1 := int(src.Cb[s00j]) - 128
- s00cr1 := int(src.Cr[s00j]) - 128
- s00ru := (s00yy1 + 91881*s00cr1) >> 8
- s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
- s00bu := (s00yy1 + 116130*s00cb1) >> 8
- if s00ru < 0 {
- s00ru = 0
- } else if s00ru > 0xffff {
- s00ru = 0xffff
- }
- if s00gu < 0 {
- s00gu = 0
- } else if s00gu > 0xffff {
- s00gu = 0xffff
- }
- if s00bu < 0 {
- s00bu = 0
- } else if s00bu > 0xffff {
- s00bu = 0xffff
- }
-
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
- s10j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i]) * 0x10101
- s10cb1 := int(src.Cb[s10j]) - 128
- s10cr1 := int(src.Cr[s10j]) - 128
- s10ru := (s10yy1 + 91881*s10cr1) >> 8
- s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
- s10bu := (s10yy1 + 116130*s10cb1) >> 8
- if s10ru < 0 {
- s10ru = 0
- } else if s10ru > 0xffff {
- s10ru = 0xffff
- }
- if s10gu < 0 {
- s10gu = 0
- } else if s10gu > 0xffff {
- s10gu = 0xffff
- }
- if s10bu < 0 {
- s10bu = 0
- } else if s10bu > 0xffff {
- s10bu = 0xffff
- }
-
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
- s01j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i]) * 0x10101
- s01cb1 := int(src.Cb[s01j]) - 128
- s01cr1 := int(src.Cr[s01j]) - 128
- s01ru := (s01yy1 + 91881*s01cr1) >> 8
- s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
- s01bu := (s01yy1 + 116130*s01cb1) >> 8
- if s01ru < 0 {
- s01ru = 0
- } else if s01ru > 0xffff {
- s01ru = 0xffff
- }
- if s01gu < 0 {
- s01gu = 0
- } else if s01gu > 0xffff {
- s01gu = 0xffff
- }
- if s01bu < 0 {
- s01bu = 0
- } else if s01bu > 0xffff {
- s01bu = 0xffff
- }
-
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
- s11j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i]) * 0x10101
- s11cb1 := int(src.Cb[s11j]) - 128
- s11cr1 := int(src.Cr[s11j]) - 128
- s11ru := (s11yy1 + 91881*s11cr1) >> 8
- s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
- s11bu := (s11yy1 + 116130*s11cb1) >> 8
- if s11ru < 0 {
- s11ru = 0
- } else if s11ru > 0xffff {
- s11ru = 0xffff
- }
- if s11gu < 0 {
- s11gu = 0
- } else if s11gu > 0xffff {
- s11gu = 0xffff
- }
- if s11bu < 0 {
- s11bu = 0
- } else if s11bu > 0xffff {
- s11bu = 0xffff
- }
-
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- pr := uint32(s11r)
- pg := uint32(s11g)
- pb := uint32(s11b)
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (ablInterpolator) scale_RGBA_Image_Over(dst *image.RGBA, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) {
- sw := int32(sr.Dx())
- sh := int32(sr.Dy())
- yscale := float64(sh) / float64(dr.Dy())
- xscale := float64(sw) / float64(dr.Dx())
- swMinus1, shMinus1 := sw-1, sh-1
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (float64(dy)+0.5)*yscale - 0.5
- // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
- // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
- // sx, below.
- sy0 := int32(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy1 := sy0 + 1
- if sy < 0 {
- sy0, sy1 = 0, 0
- yFrac0, yFrac1 = 0, 1
- } else if sy1 > shMinus1 {
- sy0, sy1 = shMinus1, shMinus1
- yFrac0, yFrac1 = 1, 0
- }
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
-
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (float64(dx)+0.5)*xscale - 0.5
- sx0 := int32(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx1 := sx0 + 1
- if sx < 0 {
- sx0, sx1 = 0, 0
- xFrac0, xFrac1 = 0, 1
- } else if sx1 > swMinus1 {
- sx0, sx1 = swMinus1, swMinus1
- xFrac0, xFrac1 = 1, 0
- }
-
- s00ru, s00gu, s00bu, s00au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0)).RGBA()
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s00a := float64(s00au)
- s10ru, s10gu, s10bu, s10au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0)).RGBA()
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10a := float64(s10au)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s10a = xFrac1*s00a + xFrac0*s10a
- s01ru, s01gu, s01bu, s01au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1)).RGBA()
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s01a := float64(s01au)
- s11ru, s11gu, s11bu, s11au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1)).RGBA()
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11a := float64(s11au)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11a = xFrac1*s01a + xFrac0*s11a
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- s11a = yFrac1*s10a + yFrac0*s11a
- pr := uint32(s11r)
- pg := uint32(s11g)
- pb := uint32(s11b)
- pa := uint32(s11a)
- pa1 := (0xffff - pa) * 0x101
- dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
- dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
- dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
- dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
- }
- }
-}
-
-func (ablInterpolator) scale_RGBA_Image_Src(dst *image.RGBA, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) {
- sw := int32(sr.Dx())
- sh := int32(sr.Dy())
- yscale := float64(sh) / float64(dr.Dy())
- xscale := float64(sw) / float64(dr.Dx())
- swMinus1, shMinus1 := sw-1, sh-1
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (float64(dy)+0.5)*yscale - 0.5
- // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
- // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
- // sx, below.
- sy0 := int32(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy1 := sy0 + 1
- if sy < 0 {
- sy0, sy1 = 0, 0
- yFrac0, yFrac1 = 0, 1
- } else if sy1 > shMinus1 {
- sy0, sy1 = shMinus1, shMinus1
- yFrac0, yFrac1 = 1, 0
- }
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
-
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (float64(dx)+0.5)*xscale - 0.5
- sx0 := int32(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx1 := sx0 + 1
- if sx < 0 {
- sx0, sx1 = 0, 0
- xFrac0, xFrac1 = 0, 1
- } else if sx1 > swMinus1 {
- sx0, sx1 = swMinus1, swMinus1
- xFrac0, xFrac1 = 1, 0
- }
-
- s00ru, s00gu, s00bu, s00au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0)).RGBA()
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s00a := float64(s00au)
- s10ru, s10gu, s10bu, s10au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0)).RGBA()
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10a := float64(s10au)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s10a = xFrac1*s00a + xFrac0*s10a
- s01ru, s01gu, s01bu, s01au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1)).RGBA()
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s01a := float64(s01au)
- s11ru, s11gu, s11bu, s11au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1)).RGBA()
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11a := float64(s11au)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11a = xFrac1*s01a + xFrac0*s11a
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- s11a = yFrac1*s10a + yFrac0*s11a
- pr := uint32(s11r)
- pg := uint32(s11g)
- pb := uint32(s11b)
- pa := uint32(s11a)
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = uint8(pa >> 8)
- }
- }
-}
-
-func (ablInterpolator) scale_Image_Image_Over(dst Image, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) {
- sw := int32(sr.Dx())
- sh := int32(sr.Dy())
- yscale := float64(sh) / float64(dr.Dy())
- xscale := float64(sw) / float64(dr.Dx())
- swMinus1, shMinus1 := sw-1, sh-1
- srcMask, smp := opts.SrcMask, opts.SrcMaskP
- dstMask, dmp := opts.DstMask, opts.DstMaskP
- dstColorRGBA64 := &color.RGBA64{}
- dstColor := color.Color(dstColorRGBA64)
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (float64(dy)+0.5)*yscale - 0.5
- // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
- // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
- // sx, below.
- sy0 := int32(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy1 := sy0 + 1
- if sy < 0 {
- sy0, sy1 = 0, 0
- yFrac0, yFrac1 = 0, 1
- } else if sy1 > shMinus1 {
- sy0, sy1 = shMinus1, shMinus1
- yFrac0, yFrac1 = 1, 0
- }
-
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
- sx := (float64(dx)+0.5)*xscale - 0.5
- sx0 := int32(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx1 := sx0 + 1
- if sx < 0 {
- sx0, sx1 = 0, 0
- xFrac0, xFrac1 = 0, 1
- } else if sx1 > swMinus1 {
- sx0, sx1 = swMinus1, swMinus1
- xFrac0, xFrac1 = 1, 0
- }
-
- s00ru, s00gu, s00bu, s00au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0)).RGBA()
- if srcMask != nil {
- _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx0), smp.Y+sr.Min.Y+int(sy0)).RGBA()
- s00ru = s00ru * ma / 0xffff
- s00gu = s00gu * ma / 0xffff
- s00bu = s00bu * ma / 0xffff
- s00au = s00au * ma / 0xffff
- }
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s00a := float64(s00au)
- s10ru, s10gu, s10bu, s10au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0)).RGBA()
- if srcMask != nil {
- _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx1), smp.Y+sr.Min.Y+int(sy0)).RGBA()
- s10ru = s10ru * ma / 0xffff
- s10gu = s10gu * ma / 0xffff
- s10bu = s10bu * ma / 0xffff
- s10au = s10au * ma / 0xffff
- }
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10a := float64(s10au)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s10a = xFrac1*s00a + xFrac0*s10a
- s01ru, s01gu, s01bu, s01au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1)).RGBA()
- if srcMask != nil {
- _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx0), smp.Y+sr.Min.Y+int(sy1)).RGBA()
- s01ru = s01ru * ma / 0xffff
- s01gu = s01gu * ma / 0xffff
- s01bu = s01bu * ma / 0xffff
- s01au = s01au * ma / 0xffff
- }
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s01a := float64(s01au)
- s11ru, s11gu, s11bu, s11au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1)).RGBA()
- if srcMask != nil {
- _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx1), smp.Y+sr.Min.Y+int(sy1)).RGBA()
- s11ru = s11ru * ma / 0xffff
- s11gu = s11gu * ma / 0xffff
- s11bu = s11bu * ma / 0xffff
- s11au = s11au * ma / 0xffff
- }
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11a := float64(s11au)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11a = xFrac1*s01a + xFrac0*s11a
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- s11a = yFrac1*s10a + yFrac0*s11a
- pr := uint32(s11r)
- pg := uint32(s11g)
- pb := uint32(s11b)
- pa := uint32(s11a)
- qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
- if dstMask != nil {
- _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
- pr = pr * ma / 0xffff
- pg = pg * ma / 0xffff
- pb = pb * ma / 0xffff
- pa = pa * ma / 0xffff
- }
- pa1 := 0xffff - pa
- dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
- dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
- dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
- dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
- dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
- }
- }
-}
-
-func (ablInterpolator) scale_Image_Image_Src(dst Image, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) {
- sw := int32(sr.Dx())
- sh := int32(sr.Dy())
- yscale := float64(sh) / float64(dr.Dy())
- xscale := float64(sw) / float64(dr.Dx())
- swMinus1, shMinus1 := sw-1, sh-1
- srcMask, smp := opts.SrcMask, opts.SrcMaskP
- dstMask, dmp := opts.DstMask, opts.DstMaskP
- dstColorRGBA64 := &color.RGBA64{}
- dstColor := color.Color(dstColorRGBA64)
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (float64(dy)+0.5)*yscale - 0.5
- // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
- // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
- // sx, below.
- sy0 := int32(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy1 := sy0 + 1
- if sy < 0 {
- sy0, sy1 = 0, 0
- yFrac0, yFrac1 = 0, 1
- } else if sy1 > shMinus1 {
- sy0, sy1 = shMinus1, shMinus1
- yFrac0, yFrac1 = 1, 0
- }
-
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
- sx := (float64(dx)+0.5)*xscale - 0.5
- sx0 := int32(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx1 := sx0 + 1
- if sx < 0 {
- sx0, sx1 = 0, 0
- xFrac0, xFrac1 = 0, 1
- } else if sx1 > swMinus1 {
- sx0, sx1 = swMinus1, swMinus1
- xFrac0, xFrac1 = 1, 0
- }
-
- s00ru, s00gu, s00bu, s00au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0)).RGBA()
- if srcMask != nil {
- _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx0), smp.Y+sr.Min.Y+int(sy0)).RGBA()
- s00ru = s00ru * ma / 0xffff
- s00gu = s00gu * ma / 0xffff
- s00bu = s00bu * ma / 0xffff
- s00au = s00au * ma / 0xffff
- }
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s00a := float64(s00au)
- s10ru, s10gu, s10bu, s10au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0)).RGBA()
- if srcMask != nil {
- _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx1), smp.Y+sr.Min.Y+int(sy0)).RGBA()
- s10ru = s10ru * ma / 0xffff
- s10gu = s10gu * ma / 0xffff
- s10bu = s10bu * ma / 0xffff
- s10au = s10au * ma / 0xffff
- }
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10a := float64(s10au)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s10a = xFrac1*s00a + xFrac0*s10a
- s01ru, s01gu, s01bu, s01au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1)).RGBA()
- if srcMask != nil {
- _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx0), smp.Y+sr.Min.Y+int(sy1)).RGBA()
- s01ru = s01ru * ma / 0xffff
- s01gu = s01gu * ma / 0xffff
- s01bu = s01bu * ma / 0xffff
- s01au = s01au * ma / 0xffff
- }
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s01a := float64(s01au)
- s11ru, s11gu, s11bu, s11au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1)).RGBA()
- if srcMask != nil {
- _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx1), smp.Y+sr.Min.Y+int(sy1)).RGBA()
- s11ru = s11ru * ma / 0xffff
- s11gu = s11gu * ma / 0xffff
- s11bu = s11bu * ma / 0xffff
- s11au = s11au * ma / 0xffff
- }
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11a := float64(s11au)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11a = xFrac1*s01a + xFrac0*s11a
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- s11a = yFrac1*s10a + yFrac0*s11a
- pr := uint32(s11r)
- pg := uint32(s11g)
- pb := uint32(s11b)
- pa := uint32(s11a)
- if dstMask != nil {
- qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
- _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
- pr = pr * ma / 0xffff
- pg = pg * ma / 0xffff
- pb = pb * ma / 0xffff
- pa = pa * ma / 0xffff
- pa1 := 0xffff - ma
- dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
- dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
- dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
- dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
- dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
- } else {
- dstColorRGBA64.R = uint16(pr)
- dstColorRGBA64.G = uint16(pg)
- dstColorRGBA64.B = uint16(pb)
- dstColorRGBA64.A = uint16(pa)
- dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
- }
- }
- }
-}
-
-func (ablInterpolator) transform_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.Gray, sr image.Rectangle, bias image.Point, opts *Options) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- sx -= 0.5
- sx0 := int(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx0 += bias.X
- sx1 := sx0 + 1
- if sx0 < sr.Min.X {
- sx0, sx1 = sr.Min.X, sr.Min.X
- xFrac0, xFrac1 = 0, 1
- } else if sx1 >= sr.Max.X {
- sx0, sx1 = sr.Max.X-1, sr.Max.X-1
- xFrac0, xFrac1 = 1, 0
- }
-
- sy -= 0.5
- sy0 := int(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy0 += bias.Y
- sy1 := sy0 + 1
- if sy0 < sr.Min.Y {
- sy0, sy1 = sr.Min.Y, sr.Min.Y
- yFrac0, yFrac1 = 0, 1
- } else if sy1 >= sr.Max.Y {
- sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
- yFrac0, yFrac1 = 1, 0
- }
-
- s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0 - src.Rect.Min.X)
- s00ru := uint32(src.Pix[s00i]) * 0x101
- s00r := float64(s00ru)
- s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1 - src.Rect.Min.X)
- s10ru := uint32(src.Pix[s10i]) * 0x101
- s10r := float64(s10ru)
- s10r = xFrac1*s00r + xFrac0*s10r
- s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0 - src.Rect.Min.X)
- s01ru := uint32(src.Pix[s01i]) * 0x101
- s01r := float64(s01ru)
- s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1 - src.Rect.Min.X)
- s11ru := uint32(src.Pix[s11i]) * 0x101
- s11r := float64(s11ru)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11r = yFrac1*s10r + yFrac0*s11r
- pr := uint32(s11r)
- out := uint8(pr >> 8)
- dst.Pix[d+0] = out
- dst.Pix[d+1] = out
- dst.Pix[d+2] = out
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (ablInterpolator) transform_RGBA_NRGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.NRGBA, sr image.Rectangle, bias image.Point, opts *Options) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- sx -= 0.5
- sx0 := int(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx0 += bias.X
- sx1 := sx0 + 1
- if sx0 < sr.Min.X {
- sx0, sx1 = sr.Min.X, sr.Min.X
- xFrac0, xFrac1 = 0, 1
- } else if sx1 >= sr.Max.X {
- sx0, sx1 = sr.Max.X-1, sr.Max.X-1
- xFrac0, xFrac1 = 1, 0
- }
-
- sy -= 0.5
- sy0 := int(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy0 += bias.Y
- sy1 := sy0 + 1
- if sy0 < sr.Min.Y {
- sy0, sy1 = sr.Min.Y, sr.Min.Y
- yFrac0, yFrac1 = 0, 1
- } else if sy1 >= sr.Max.Y {
- sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
- yFrac0, yFrac1 = 1, 0
- }
-
- s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
- s00au := uint32(src.Pix[s00i+3]) * 0x101
- s00ru := uint32(src.Pix[s00i+0]) * s00au / 0xff
- s00gu := uint32(src.Pix[s00i+1]) * s00au / 0xff
- s00bu := uint32(src.Pix[s00i+2]) * s00au / 0xff
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s00a := float64(s00au)
- s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
- s10au := uint32(src.Pix[s10i+3]) * 0x101
- s10ru := uint32(src.Pix[s10i+0]) * s10au / 0xff
- s10gu := uint32(src.Pix[s10i+1]) * s10au / 0xff
- s10bu := uint32(src.Pix[s10i+2]) * s10au / 0xff
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10a := float64(s10au)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s10a = xFrac1*s00a + xFrac0*s10a
- s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
- s01au := uint32(src.Pix[s01i+3]) * 0x101
- s01ru := uint32(src.Pix[s01i+0]) * s01au / 0xff
- s01gu := uint32(src.Pix[s01i+1]) * s01au / 0xff
- s01bu := uint32(src.Pix[s01i+2]) * s01au / 0xff
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s01a := float64(s01au)
- s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
- s11au := uint32(src.Pix[s11i+3]) * 0x101
- s11ru := uint32(src.Pix[s11i+0]) * s11au / 0xff
- s11gu := uint32(src.Pix[s11i+1]) * s11au / 0xff
- s11bu := uint32(src.Pix[s11i+2]) * s11au / 0xff
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11a := float64(s11au)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11a = xFrac1*s01a + xFrac0*s11a
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- s11a = yFrac1*s10a + yFrac0*s11a
- pr := uint32(s11r)
- pg := uint32(s11g)
- pb := uint32(s11b)
- pa := uint32(s11a)
- pa1 := (0xffff - pa) * 0x101
- dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
- dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
- dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
- dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
- }
- }
-}
-
-func (ablInterpolator) transform_RGBA_NRGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.NRGBA, sr image.Rectangle, bias image.Point, opts *Options) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- sx -= 0.5
- sx0 := int(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx0 += bias.X
- sx1 := sx0 + 1
- if sx0 < sr.Min.X {
- sx0, sx1 = sr.Min.X, sr.Min.X
- xFrac0, xFrac1 = 0, 1
- } else if sx1 >= sr.Max.X {
- sx0, sx1 = sr.Max.X-1, sr.Max.X-1
- xFrac0, xFrac1 = 1, 0
- }
-
- sy -= 0.5
- sy0 := int(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy0 += bias.Y
- sy1 := sy0 + 1
- if sy0 < sr.Min.Y {
- sy0, sy1 = sr.Min.Y, sr.Min.Y
- yFrac0, yFrac1 = 0, 1
- } else if sy1 >= sr.Max.Y {
- sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
- yFrac0, yFrac1 = 1, 0
- }
-
- s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
- s00au := uint32(src.Pix[s00i+3]) * 0x101
- s00ru := uint32(src.Pix[s00i+0]) * s00au / 0xff
- s00gu := uint32(src.Pix[s00i+1]) * s00au / 0xff
- s00bu := uint32(src.Pix[s00i+2]) * s00au / 0xff
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s00a := float64(s00au)
- s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
- s10au := uint32(src.Pix[s10i+3]) * 0x101
- s10ru := uint32(src.Pix[s10i+0]) * s10au / 0xff
- s10gu := uint32(src.Pix[s10i+1]) * s10au / 0xff
- s10bu := uint32(src.Pix[s10i+2]) * s10au / 0xff
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10a := float64(s10au)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s10a = xFrac1*s00a + xFrac0*s10a
- s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
- s01au := uint32(src.Pix[s01i+3]) * 0x101
- s01ru := uint32(src.Pix[s01i+0]) * s01au / 0xff
- s01gu := uint32(src.Pix[s01i+1]) * s01au / 0xff
- s01bu := uint32(src.Pix[s01i+2]) * s01au / 0xff
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s01a := float64(s01au)
- s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
- s11au := uint32(src.Pix[s11i+3]) * 0x101
- s11ru := uint32(src.Pix[s11i+0]) * s11au / 0xff
- s11gu := uint32(src.Pix[s11i+1]) * s11au / 0xff
- s11bu := uint32(src.Pix[s11i+2]) * s11au / 0xff
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11a := float64(s11au)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11a = xFrac1*s01a + xFrac0*s11a
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- s11a = yFrac1*s10a + yFrac0*s11a
- pr := uint32(s11r)
- pg := uint32(s11g)
- pb := uint32(s11b)
- pa := uint32(s11a)
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = uint8(pa >> 8)
- }
- }
-}
-
-func (ablInterpolator) transform_RGBA_RGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.RGBA, sr image.Rectangle, bias image.Point, opts *Options) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- sx -= 0.5
- sx0 := int(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx0 += bias.X
- sx1 := sx0 + 1
- if sx0 < sr.Min.X {
- sx0, sx1 = sr.Min.X, sr.Min.X
- xFrac0, xFrac1 = 0, 1
- } else if sx1 >= sr.Max.X {
- sx0, sx1 = sr.Max.X-1, sr.Max.X-1
- xFrac0, xFrac1 = 1, 0
- }
-
- sy -= 0.5
- sy0 := int(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy0 += bias.Y
- sy1 := sy0 + 1
- if sy0 < sr.Min.Y {
- sy0, sy1 = sr.Min.Y, sr.Min.Y
- yFrac0, yFrac1 = 0, 1
- } else if sy1 >= sr.Max.Y {
- sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
- yFrac0, yFrac1 = 1, 0
- }
-
- s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
- s00ru := uint32(src.Pix[s00i+0]) * 0x101
- s00gu := uint32(src.Pix[s00i+1]) * 0x101
- s00bu := uint32(src.Pix[s00i+2]) * 0x101
- s00au := uint32(src.Pix[s00i+3]) * 0x101
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s00a := float64(s00au)
- s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
- s10ru := uint32(src.Pix[s10i+0]) * 0x101
- s10gu := uint32(src.Pix[s10i+1]) * 0x101
- s10bu := uint32(src.Pix[s10i+2]) * 0x101
- s10au := uint32(src.Pix[s10i+3]) * 0x101
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10a := float64(s10au)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s10a = xFrac1*s00a + xFrac0*s10a
- s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
- s01ru := uint32(src.Pix[s01i+0]) * 0x101
- s01gu := uint32(src.Pix[s01i+1]) * 0x101
- s01bu := uint32(src.Pix[s01i+2]) * 0x101
- s01au := uint32(src.Pix[s01i+3]) * 0x101
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s01a := float64(s01au)
- s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
- s11ru := uint32(src.Pix[s11i+0]) * 0x101
- s11gu := uint32(src.Pix[s11i+1]) * 0x101
- s11bu := uint32(src.Pix[s11i+2]) * 0x101
- s11au := uint32(src.Pix[s11i+3]) * 0x101
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11a := float64(s11au)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11a = xFrac1*s01a + xFrac0*s11a
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- s11a = yFrac1*s10a + yFrac0*s11a
- pr := uint32(s11r)
- pg := uint32(s11g)
- pb := uint32(s11b)
- pa := uint32(s11a)
- pa1 := (0xffff - pa) * 0x101
- dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
- dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
- dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
- dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
- }
- }
-}
-
-func (ablInterpolator) transform_RGBA_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.RGBA, sr image.Rectangle, bias image.Point, opts *Options) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- sx -= 0.5
- sx0 := int(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx0 += bias.X
- sx1 := sx0 + 1
- if sx0 < sr.Min.X {
- sx0, sx1 = sr.Min.X, sr.Min.X
- xFrac0, xFrac1 = 0, 1
- } else if sx1 >= sr.Max.X {
- sx0, sx1 = sr.Max.X-1, sr.Max.X-1
- xFrac0, xFrac1 = 1, 0
- }
-
- sy -= 0.5
- sy0 := int(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy0 += bias.Y
- sy1 := sy0 + 1
- if sy0 < sr.Min.Y {
- sy0, sy1 = sr.Min.Y, sr.Min.Y
- yFrac0, yFrac1 = 0, 1
- } else if sy1 >= sr.Max.Y {
- sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
- yFrac0, yFrac1 = 1, 0
- }
-
- s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
- s00ru := uint32(src.Pix[s00i+0]) * 0x101
- s00gu := uint32(src.Pix[s00i+1]) * 0x101
- s00bu := uint32(src.Pix[s00i+2]) * 0x101
- s00au := uint32(src.Pix[s00i+3]) * 0x101
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s00a := float64(s00au)
- s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
- s10ru := uint32(src.Pix[s10i+0]) * 0x101
- s10gu := uint32(src.Pix[s10i+1]) * 0x101
- s10bu := uint32(src.Pix[s10i+2]) * 0x101
- s10au := uint32(src.Pix[s10i+3]) * 0x101
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10a := float64(s10au)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s10a = xFrac1*s00a + xFrac0*s10a
- s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
- s01ru := uint32(src.Pix[s01i+0]) * 0x101
- s01gu := uint32(src.Pix[s01i+1]) * 0x101
- s01bu := uint32(src.Pix[s01i+2]) * 0x101
- s01au := uint32(src.Pix[s01i+3]) * 0x101
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s01a := float64(s01au)
- s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
- s11ru := uint32(src.Pix[s11i+0]) * 0x101
- s11gu := uint32(src.Pix[s11i+1]) * 0x101
- s11bu := uint32(src.Pix[s11i+2]) * 0x101
- s11au := uint32(src.Pix[s11i+3]) * 0x101
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11a := float64(s11au)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11a = xFrac1*s01a + xFrac0*s11a
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- s11a = yFrac1*s10a + yFrac0*s11a
- pr := uint32(s11r)
- pg := uint32(s11g)
- pb := uint32(s11b)
- pa := uint32(s11a)
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = uint8(pa >> 8)
- }
- }
-}
-
-func (ablInterpolator) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, opts *Options) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- sx -= 0.5
- sx0 := int(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx0 += bias.X
- sx1 := sx0 + 1
- if sx0 < sr.Min.X {
- sx0, sx1 = sr.Min.X, sr.Min.X
- xFrac0, xFrac1 = 0, 1
- } else if sx1 >= sr.Max.X {
- sx0, sx1 = sr.Max.X-1, sr.Max.X-1
- xFrac0, xFrac1 = 1, 0
- }
-
- sy -= 0.5
- sy0 := int(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy0 += bias.Y
- sy1 := sy0 + 1
- if sy0 < sr.Min.Y {
- sy0, sy1 = sr.Min.Y, sr.Min.Y
- yFrac0, yFrac1 = 0, 1
- } else if sy1 >= sr.Max.Y {
- sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
- yFrac0, yFrac1 = 1, 0
- }
-
- s00i := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- s00j := (sy0-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i]) * 0x10101
- s00cb1 := int(src.Cb[s00j]) - 128
- s00cr1 := int(src.Cr[s00j]) - 128
- s00ru := (s00yy1 + 91881*s00cr1) >> 8
- s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
- s00bu := (s00yy1 + 116130*s00cb1) >> 8
- if s00ru < 0 {
- s00ru = 0
- } else if s00ru > 0xffff {
- s00ru = 0xffff
- }
- if s00gu < 0 {
- s00gu = 0
- } else if s00gu > 0xffff {
- s00gu = 0xffff
- }
- if s00bu < 0 {
- s00bu = 0
- } else if s00bu > 0xffff {
- s00bu = 0xffff
- }
-
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s10i := (sy0-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
- s10j := (sy0-src.Rect.Min.Y)*src.CStride + (sx1 - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i]) * 0x10101
- s10cb1 := int(src.Cb[s10j]) - 128
- s10cr1 := int(src.Cr[s10j]) - 128
- s10ru := (s10yy1 + 91881*s10cr1) >> 8
- s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
- s10bu := (s10yy1 + 116130*s10cb1) >> 8
- if s10ru < 0 {
- s10ru = 0
- } else if s10ru > 0xffff {
- s10ru = 0xffff
- }
- if s10gu < 0 {
- s10gu = 0
- } else if s10gu > 0xffff {
- s10gu = 0xffff
- }
- if s10bu < 0 {
- s10bu = 0
- } else if s10bu > 0xffff {
- s10bu = 0xffff
- }
-
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s01i := (sy1-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- s01j := (sy1-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i]) * 0x10101
- s01cb1 := int(src.Cb[s01j]) - 128
- s01cr1 := int(src.Cr[s01j]) - 128
- s01ru := (s01yy1 + 91881*s01cr1) >> 8
- s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
- s01bu := (s01yy1 + 116130*s01cb1) >> 8
- if s01ru < 0 {
- s01ru = 0
- } else if s01ru > 0xffff {
- s01ru = 0xffff
- }
- if s01gu < 0 {
- s01gu = 0
- } else if s01gu > 0xffff {
- s01gu = 0xffff
- }
- if s01bu < 0 {
- s01bu = 0
- } else if s01bu > 0xffff {
- s01bu = 0xffff
- }
-
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s11i := (sy1-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
- s11j := (sy1-src.Rect.Min.Y)*src.CStride + (sx1 - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i]) * 0x10101
- s11cb1 := int(src.Cb[s11j]) - 128
- s11cr1 := int(src.Cr[s11j]) - 128
- s11ru := (s11yy1 + 91881*s11cr1) >> 8
- s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
- s11bu := (s11yy1 + 116130*s11cb1) >> 8
- if s11ru < 0 {
- s11ru = 0
- } else if s11ru > 0xffff {
- s11ru = 0xffff
- }
- if s11gu < 0 {
- s11gu = 0
- } else if s11gu > 0xffff {
- s11gu = 0xffff
- }
- if s11bu < 0 {
- s11bu = 0
- } else if s11bu > 0xffff {
- s11bu = 0xffff
- }
-
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- pr := uint32(s11r)
- pg := uint32(s11g)
- pb := uint32(s11b)
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (ablInterpolator) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, opts *Options) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- sx -= 0.5
- sx0 := int(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx0 += bias.X
- sx1 := sx0 + 1
- if sx0 < sr.Min.X {
- sx0, sx1 = sr.Min.X, sr.Min.X
- xFrac0, xFrac1 = 0, 1
- } else if sx1 >= sr.Max.X {
- sx0, sx1 = sr.Max.X-1, sr.Max.X-1
- xFrac0, xFrac1 = 1, 0
- }
-
- sy -= 0.5
- sy0 := int(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy0 += bias.Y
- sy1 := sy0 + 1
- if sy0 < sr.Min.Y {
- sy0, sy1 = sr.Min.Y, sr.Min.Y
- yFrac0, yFrac1 = 0, 1
- } else if sy1 >= sr.Max.Y {
- sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
- yFrac0, yFrac1 = 1, 0
- }
-
- s00i := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- s00j := (sy0-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i]) * 0x10101
- s00cb1 := int(src.Cb[s00j]) - 128
- s00cr1 := int(src.Cr[s00j]) - 128
- s00ru := (s00yy1 + 91881*s00cr1) >> 8
- s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
- s00bu := (s00yy1 + 116130*s00cb1) >> 8
- if s00ru < 0 {
- s00ru = 0
- } else if s00ru > 0xffff {
- s00ru = 0xffff
- }
- if s00gu < 0 {
- s00gu = 0
- } else if s00gu > 0xffff {
- s00gu = 0xffff
- }
- if s00bu < 0 {
- s00bu = 0
- } else if s00bu > 0xffff {
- s00bu = 0xffff
- }
-
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s10i := (sy0-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
- s10j := (sy0-src.Rect.Min.Y)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i]) * 0x10101
- s10cb1 := int(src.Cb[s10j]) - 128
- s10cr1 := int(src.Cr[s10j]) - 128
- s10ru := (s10yy1 + 91881*s10cr1) >> 8
- s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
- s10bu := (s10yy1 + 116130*s10cb1) >> 8
- if s10ru < 0 {
- s10ru = 0
- } else if s10ru > 0xffff {
- s10ru = 0xffff
- }
- if s10gu < 0 {
- s10gu = 0
- } else if s10gu > 0xffff {
- s10gu = 0xffff
- }
- if s10bu < 0 {
- s10bu = 0
- } else if s10bu > 0xffff {
- s10bu = 0xffff
- }
-
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s01i := (sy1-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- s01j := (sy1-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i]) * 0x10101
- s01cb1 := int(src.Cb[s01j]) - 128
- s01cr1 := int(src.Cr[s01j]) - 128
- s01ru := (s01yy1 + 91881*s01cr1) >> 8
- s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
- s01bu := (s01yy1 + 116130*s01cb1) >> 8
- if s01ru < 0 {
- s01ru = 0
- } else if s01ru > 0xffff {
- s01ru = 0xffff
- }
- if s01gu < 0 {
- s01gu = 0
- } else if s01gu > 0xffff {
- s01gu = 0xffff
- }
- if s01bu < 0 {
- s01bu = 0
- } else if s01bu > 0xffff {
- s01bu = 0xffff
- }
-
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s11i := (sy1-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
- s11j := (sy1-src.Rect.Min.Y)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i]) * 0x10101
- s11cb1 := int(src.Cb[s11j]) - 128
- s11cr1 := int(src.Cr[s11j]) - 128
- s11ru := (s11yy1 + 91881*s11cr1) >> 8
- s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
- s11bu := (s11yy1 + 116130*s11cb1) >> 8
- if s11ru < 0 {
- s11ru = 0
- } else if s11ru > 0xffff {
- s11ru = 0xffff
- }
- if s11gu < 0 {
- s11gu = 0
- } else if s11gu > 0xffff {
- s11gu = 0xffff
- }
- if s11bu < 0 {
- s11bu = 0
- } else if s11bu > 0xffff {
- s11bu = 0xffff
- }
-
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- pr := uint32(s11r)
- pg := uint32(s11g)
- pb := uint32(s11b)
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (ablInterpolator) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, opts *Options) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- sx -= 0.5
- sx0 := int(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx0 += bias.X
- sx1 := sx0 + 1
- if sx0 < sr.Min.X {
- sx0, sx1 = sr.Min.X, sr.Min.X
- xFrac0, xFrac1 = 0, 1
- } else if sx1 >= sr.Max.X {
- sx0, sx1 = sr.Max.X-1, sr.Max.X-1
- xFrac0, xFrac1 = 1, 0
- }
-
- sy -= 0.5
- sy0 := int(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy0 += bias.Y
- sy1 := sy0 + 1
- if sy0 < sr.Min.Y {
- sy0, sy1 = sr.Min.Y, sr.Min.Y
- yFrac0, yFrac1 = 0, 1
- } else if sy1 >= sr.Max.Y {
- sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
- yFrac0, yFrac1 = 1, 0
- }
-
- s00i := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- s00j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i]) * 0x10101
- s00cb1 := int(src.Cb[s00j]) - 128
- s00cr1 := int(src.Cr[s00j]) - 128
- s00ru := (s00yy1 + 91881*s00cr1) >> 8
- s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
- s00bu := (s00yy1 + 116130*s00cb1) >> 8
- if s00ru < 0 {
- s00ru = 0
- } else if s00ru > 0xffff {
- s00ru = 0xffff
- }
- if s00gu < 0 {
- s00gu = 0
- } else if s00gu > 0xffff {
- s00gu = 0xffff
- }
- if s00bu < 0 {
- s00bu = 0
- } else if s00bu > 0xffff {
- s00bu = 0xffff
- }
-
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s10i := (sy0-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
- s10j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i]) * 0x10101
- s10cb1 := int(src.Cb[s10j]) - 128
- s10cr1 := int(src.Cr[s10j]) - 128
- s10ru := (s10yy1 + 91881*s10cr1) >> 8
- s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
- s10bu := (s10yy1 + 116130*s10cb1) >> 8
- if s10ru < 0 {
- s10ru = 0
- } else if s10ru > 0xffff {
- s10ru = 0xffff
- }
- if s10gu < 0 {
- s10gu = 0
- } else if s10gu > 0xffff {
- s10gu = 0xffff
- }
- if s10bu < 0 {
- s10bu = 0
- } else if s10bu > 0xffff {
- s10bu = 0xffff
- }
-
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s01i := (sy1-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- s01j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i]) * 0x10101
- s01cb1 := int(src.Cb[s01j]) - 128
- s01cr1 := int(src.Cr[s01j]) - 128
- s01ru := (s01yy1 + 91881*s01cr1) >> 8
- s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
- s01bu := (s01yy1 + 116130*s01cb1) >> 8
- if s01ru < 0 {
- s01ru = 0
- } else if s01ru > 0xffff {
- s01ru = 0xffff
- }
- if s01gu < 0 {
- s01gu = 0
- } else if s01gu > 0xffff {
- s01gu = 0xffff
- }
- if s01bu < 0 {
- s01bu = 0
- } else if s01bu > 0xffff {
- s01bu = 0xffff
- }
-
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s11i := (sy1-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
- s11j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i]) * 0x10101
- s11cb1 := int(src.Cb[s11j]) - 128
- s11cr1 := int(src.Cr[s11j]) - 128
- s11ru := (s11yy1 + 91881*s11cr1) >> 8
- s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
- s11bu := (s11yy1 + 116130*s11cb1) >> 8
- if s11ru < 0 {
- s11ru = 0
- } else if s11ru > 0xffff {
- s11ru = 0xffff
- }
- if s11gu < 0 {
- s11gu = 0
- } else if s11gu > 0xffff {
- s11gu = 0xffff
- }
- if s11bu < 0 {
- s11bu = 0
- } else if s11bu > 0xffff {
- s11bu = 0xffff
- }
-
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- pr := uint32(s11r)
- pg := uint32(s11g)
- pb := uint32(s11b)
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (ablInterpolator) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, opts *Options) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- sx -= 0.5
- sx0 := int(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx0 += bias.X
- sx1 := sx0 + 1
- if sx0 < sr.Min.X {
- sx0, sx1 = sr.Min.X, sr.Min.X
- xFrac0, xFrac1 = 0, 1
- } else if sx1 >= sr.Max.X {
- sx0, sx1 = sr.Max.X-1, sr.Max.X-1
- xFrac0, xFrac1 = 1, 0
- }
-
- sy -= 0.5
- sy0 := int(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy0 += bias.Y
- sy1 := sy0 + 1
- if sy0 < sr.Min.Y {
- sy0, sy1 = sr.Min.Y, sr.Min.Y
- yFrac0, yFrac1 = 0, 1
- } else if sy1 >= sr.Max.Y {
- sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
- yFrac0, yFrac1 = 1, 0
- }
-
- s00i := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- s00j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i]) * 0x10101
- s00cb1 := int(src.Cb[s00j]) - 128
- s00cr1 := int(src.Cr[s00j]) - 128
- s00ru := (s00yy1 + 91881*s00cr1) >> 8
- s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
- s00bu := (s00yy1 + 116130*s00cb1) >> 8
- if s00ru < 0 {
- s00ru = 0
- } else if s00ru > 0xffff {
- s00ru = 0xffff
- }
- if s00gu < 0 {
- s00gu = 0
- } else if s00gu > 0xffff {
- s00gu = 0xffff
- }
- if s00bu < 0 {
- s00bu = 0
- } else if s00bu > 0xffff {
- s00bu = 0xffff
- }
-
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s10i := (sy0-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
- s10j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx1 - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i]) * 0x10101
- s10cb1 := int(src.Cb[s10j]) - 128
- s10cr1 := int(src.Cr[s10j]) - 128
- s10ru := (s10yy1 + 91881*s10cr1) >> 8
- s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
- s10bu := (s10yy1 + 116130*s10cb1) >> 8
- if s10ru < 0 {
- s10ru = 0
- } else if s10ru > 0xffff {
- s10ru = 0xffff
- }
- if s10gu < 0 {
- s10gu = 0
- } else if s10gu > 0xffff {
- s10gu = 0xffff
- }
- if s10bu < 0 {
- s10bu = 0
- } else if s10bu > 0xffff {
- s10bu = 0xffff
- }
-
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s01i := (sy1-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- s01j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i]) * 0x10101
- s01cb1 := int(src.Cb[s01j]) - 128
- s01cr1 := int(src.Cr[s01j]) - 128
- s01ru := (s01yy1 + 91881*s01cr1) >> 8
- s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
- s01bu := (s01yy1 + 116130*s01cb1) >> 8
- if s01ru < 0 {
- s01ru = 0
- } else if s01ru > 0xffff {
- s01ru = 0xffff
- }
- if s01gu < 0 {
- s01gu = 0
- } else if s01gu > 0xffff {
- s01gu = 0xffff
- }
- if s01bu < 0 {
- s01bu = 0
- } else if s01bu > 0xffff {
- s01bu = 0xffff
- }
-
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s11i := (sy1-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
- s11j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + (sx1 - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i]) * 0x10101
- s11cb1 := int(src.Cb[s11j]) - 128
- s11cr1 := int(src.Cr[s11j]) - 128
- s11ru := (s11yy1 + 91881*s11cr1) >> 8
- s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
- s11bu := (s11yy1 + 116130*s11cb1) >> 8
- if s11ru < 0 {
- s11ru = 0
- } else if s11ru > 0xffff {
- s11ru = 0xffff
- }
- if s11gu < 0 {
- s11gu = 0
- } else if s11gu > 0xffff {
- s11gu = 0xffff
- }
- if s11bu < 0 {
- s11bu = 0
- } else if s11bu > 0xffff {
- s11bu = 0xffff
- }
-
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- pr := uint32(s11r)
- pg := uint32(s11g)
- pb := uint32(s11b)
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (ablInterpolator) transform_RGBA_Image_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- sx -= 0.5
- sx0 := int(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx0 += bias.X
- sx1 := sx0 + 1
- if sx0 < sr.Min.X {
- sx0, sx1 = sr.Min.X, sr.Min.X
- xFrac0, xFrac1 = 0, 1
- } else if sx1 >= sr.Max.X {
- sx0, sx1 = sr.Max.X-1, sr.Max.X-1
- xFrac0, xFrac1 = 1, 0
- }
-
- sy -= 0.5
- sy0 := int(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy0 += bias.Y
- sy1 := sy0 + 1
- if sy0 < sr.Min.Y {
- sy0, sy1 = sr.Min.Y, sr.Min.Y
- yFrac0, yFrac1 = 0, 1
- } else if sy1 >= sr.Max.Y {
- sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
- yFrac0, yFrac1 = 1, 0
- }
-
- s00ru, s00gu, s00bu, s00au := src.At(sx0, sy0).RGBA()
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s00a := float64(s00au)
- s10ru, s10gu, s10bu, s10au := src.At(sx1, sy0).RGBA()
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10a := float64(s10au)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s10a = xFrac1*s00a + xFrac0*s10a
- s01ru, s01gu, s01bu, s01au := src.At(sx0, sy1).RGBA()
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s01a := float64(s01au)
- s11ru, s11gu, s11bu, s11au := src.At(sx1, sy1).RGBA()
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11a := float64(s11au)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11a = xFrac1*s01a + xFrac0*s11a
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- s11a = yFrac1*s10a + yFrac0*s11a
- pr := uint32(s11r)
- pg := uint32(s11g)
- pb := uint32(s11b)
- pa := uint32(s11a)
- pa1 := (0xffff - pa) * 0x101
- dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
- dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
- dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
- dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
- }
- }
-}
-
-func (ablInterpolator) transform_RGBA_Image_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- sx -= 0.5
- sx0 := int(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx0 += bias.X
- sx1 := sx0 + 1
- if sx0 < sr.Min.X {
- sx0, sx1 = sr.Min.X, sr.Min.X
- xFrac0, xFrac1 = 0, 1
- } else if sx1 >= sr.Max.X {
- sx0, sx1 = sr.Max.X-1, sr.Max.X-1
- xFrac0, xFrac1 = 1, 0
- }
-
- sy -= 0.5
- sy0 := int(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy0 += bias.Y
- sy1 := sy0 + 1
- if sy0 < sr.Min.Y {
- sy0, sy1 = sr.Min.Y, sr.Min.Y
- yFrac0, yFrac1 = 0, 1
- } else if sy1 >= sr.Max.Y {
- sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
- yFrac0, yFrac1 = 1, 0
- }
-
- s00ru, s00gu, s00bu, s00au := src.At(sx0, sy0).RGBA()
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s00a := float64(s00au)
- s10ru, s10gu, s10bu, s10au := src.At(sx1, sy0).RGBA()
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10a := float64(s10au)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s10a = xFrac1*s00a + xFrac0*s10a
- s01ru, s01gu, s01bu, s01au := src.At(sx0, sy1).RGBA()
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s01a := float64(s01au)
- s11ru, s11gu, s11bu, s11au := src.At(sx1, sy1).RGBA()
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11a := float64(s11au)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11a = xFrac1*s01a + xFrac0*s11a
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- s11a = yFrac1*s10a + yFrac0*s11a
- pr := uint32(s11r)
- pg := uint32(s11g)
- pb := uint32(s11b)
- pa := uint32(s11a)
- dst.Pix[d+0] = uint8(pr >> 8)
- dst.Pix[d+1] = uint8(pg >> 8)
- dst.Pix[d+2] = uint8(pb >> 8)
- dst.Pix[d+3] = uint8(pa >> 8)
- }
- }
-}
-
-func (ablInterpolator) transform_Image_Image_Over(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
- srcMask, smp := opts.SrcMask, opts.SrcMaskP
- dstMask, dmp := opts.DstMask, opts.DstMaskP
- dstColorRGBA64 := &color.RGBA64{}
- dstColor := color.Color(dstColorRGBA64)
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- sx -= 0.5
- sx0 := int(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx0 += bias.X
- sx1 := sx0 + 1
- if sx0 < sr.Min.X {
- sx0, sx1 = sr.Min.X, sr.Min.X
- xFrac0, xFrac1 = 0, 1
- } else if sx1 >= sr.Max.X {
- sx0, sx1 = sr.Max.X-1, sr.Max.X-1
- xFrac0, xFrac1 = 1, 0
- }
-
- sy -= 0.5
- sy0 := int(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy0 += bias.Y
- sy1 := sy0 + 1
- if sy0 < sr.Min.Y {
- sy0, sy1 = sr.Min.Y, sr.Min.Y
- yFrac0, yFrac1 = 0, 1
- } else if sy1 >= sr.Max.Y {
- sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
- yFrac0, yFrac1 = 1, 0
- }
-
- s00ru, s00gu, s00bu, s00au := src.At(sx0, sy0).RGBA()
- if srcMask != nil {
- _, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy0).RGBA()
- s00ru = s00ru * ma / 0xffff
- s00gu = s00gu * ma / 0xffff
- s00bu = s00bu * ma / 0xffff
- s00au = s00au * ma / 0xffff
- }
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s00a := float64(s00au)
- s10ru, s10gu, s10bu, s10au := src.At(sx1, sy0).RGBA()
- if srcMask != nil {
- _, _, _, ma := srcMask.At(smp.X+sx1, smp.Y+sy0).RGBA()
- s10ru = s10ru * ma / 0xffff
- s10gu = s10gu * ma / 0xffff
- s10bu = s10bu * ma / 0xffff
- s10au = s10au * ma / 0xffff
- }
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10a := float64(s10au)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s10a = xFrac1*s00a + xFrac0*s10a
- s01ru, s01gu, s01bu, s01au := src.At(sx0, sy1).RGBA()
- if srcMask != nil {
- _, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy1).RGBA()
- s01ru = s01ru * ma / 0xffff
- s01gu = s01gu * ma / 0xffff
- s01bu = s01bu * ma / 0xffff
- s01au = s01au * ma / 0xffff
- }
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s01a := float64(s01au)
- s11ru, s11gu, s11bu, s11au := src.At(sx1, sy1).RGBA()
- if srcMask != nil {
- _, _, _, ma := srcMask.At(smp.X+sx1, smp.Y+sy1).RGBA()
- s11ru = s11ru * ma / 0xffff
- s11gu = s11gu * ma / 0xffff
- s11bu = s11bu * ma / 0xffff
- s11au = s11au * ma / 0xffff
- }
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11a := float64(s11au)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11a = xFrac1*s01a + xFrac0*s11a
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- s11a = yFrac1*s10a + yFrac0*s11a
- pr := uint32(s11r)
- pg := uint32(s11g)
- pb := uint32(s11b)
- pa := uint32(s11a)
- qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
- if dstMask != nil {
- _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
- pr = pr * ma / 0xffff
- pg = pg * ma / 0xffff
- pb = pb * ma / 0xffff
- pa = pa * ma / 0xffff
- }
- pa1 := 0xffff - pa
- dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
- dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
- dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
- dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
- dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
- }
- }
-}
-
-func (ablInterpolator) transform_Image_Image_Src(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
- srcMask, smp := opts.SrcMask, opts.SrcMaskP
- dstMask, dmp := opts.DstMask, opts.DstMaskP
- dstColorRGBA64 := &color.RGBA64{}
- dstColor := color.Color(dstColorRGBA64)
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- sx -= 0.5
- sx0 := int(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx0 += bias.X
- sx1 := sx0 + 1
- if sx0 < sr.Min.X {
- sx0, sx1 = sr.Min.X, sr.Min.X
- xFrac0, xFrac1 = 0, 1
- } else if sx1 >= sr.Max.X {
- sx0, sx1 = sr.Max.X-1, sr.Max.X-1
- xFrac0, xFrac1 = 1, 0
- }
-
- sy -= 0.5
- sy0 := int(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy0 += bias.Y
- sy1 := sy0 + 1
- if sy0 < sr.Min.Y {
- sy0, sy1 = sr.Min.Y, sr.Min.Y
- yFrac0, yFrac1 = 0, 1
- } else if sy1 >= sr.Max.Y {
- sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
- yFrac0, yFrac1 = 1, 0
- }
-
- s00ru, s00gu, s00bu, s00au := src.At(sx0, sy0).RGBA()
- if srcMask != nil {
- _, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy0).RGBA()
- s00ru = s00ru * ma / 0xffff
- s00gu = s00gu * ma / 0xffff
- s00bu = s00bu * ma / 0xffff
- s00au = s00au * ma / 0xffff
- }
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s00a := float64(s00au)
- s10ru, s10gu, s10bu, s10au := src.At(sx1, sy0).RGBA()
- if srcMask != nil {
- _, _, _, ma := srcMask.At(smp.X+sx1, smp.Y+sy0).RGBA()
- s10ru = s10ru * ma / 0xffff
- s10gu = s10gu * ma / 0xffff
- s10bu = s10bu * ma / 0xffff
- s10au = s10au * ma / 0xffff
- }
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10a := float64(s10au)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s10a = xFrac1*s00a + xFrac0*s10a
- s01ru, s01gu, s01bu, s01au := src.At(sx0, sy1).RGBA()
- if srcMask != nil {
- _, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy1).RGBA()
- s01ru = s01ru * ma / 0xffff
- s01gu = s01gu * ma / 0xffff
- s01bu = s01bu * ma / 0xffff
- s01au = s01au * ma / 0xffff
- }
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s01a := float64(s01au)
- s11ru, s11gu, s11bu, s11au := src.At(sx1, sy1).RGBA()
- if srcMask != nil {
- _, _, _, ma := srcMask.At(smp.X+sx1, smp.Y+sy1).RGBA()
- s11ru = s11ru * ma / 0xffff
- s11gu = s11gu * ma / 0xffff
- s11bu = s11bu * ma / 0xffff
- s11au = s11au * ma / 0xffff
- }
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11a := float64(s11au)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11a = xFrac1*s01a + xFrac0*s11a
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- s11a = yFrac1*s10a + yFrac0*s11a
- pr := uint32(s11r)
- pg := uint32(s11g)
- pb := uint32(s11b)
- pa := uint32(s11a)
- if dstMask != nil {
- qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
- _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
- pr = pr * ma / 0xffff
- pg = pg * ma / 0xffff
- pb = pb * ma / 0xffff
- pa = pa * ma / 0xffff
- pa1 := 0xffff - ma
- dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
- dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
- dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
- dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
- dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
- } else {
- dstColorRGBA64.R = uint16(pr)
- dstColorRGBA64.G = uint16(pg)
- dstColorRGBA64.B = uint16(pb)
- dstColorRGBA64.A = uint16(pa)
- dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
- }
- }
- }
-}
-
-func (z *kernelScaler) Scale(dst Image, dr image.Rectangle, src image.Image, sr image.Rectangle, op Op, opts *Options) {
- if z.dw != int32(dr.Dx()) || z.dh != int32(dr.Dy()) || z.sw != int32(sr.Dx()) || z.sh != int32(sr.Dy()) {
- z.kernel.Scale(dst, dr, src, sr, op, opts)
- return
- }
-
- var o Options
- if opts != nil {
- o = *opts
- }
-
- // adr is the affected destination pixels.
- adr := dst.Bounds().Intersect(dr)
- adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
- if adr.Empty() || sr.Empty() {
- return
- }
- // Make adr relative to dr.Min.
- adr = adr.Sub(dr.Min)
- if op == Over && o.SrcMask == nil && opaque(src) {
- op = Src
- }
-
- if _, ok := src.(*image.Uniform); ok && o.DstMask == nil && o.SrcMask == nil && sr.In(src.Bounds()) {
- Draw(dst, dr, src, src.Bounds().Min, op)
- return
- }
-
- // Create a temporary buffer:
- // scaleX distributes the source image's columns over the temporary image.
- // scaleY distributes the temporary image's rows over the destination image.
- var tmp [][4]float64
- if z.pool.New != nil {
- tmpp := z.pool.Get().(*[][4]float64)
- defer z.pool.Put(tmpp)
- tmp = *tmpp
- } else {
- tmp = z.makeTmpBuf()
- }
-
- // sr is the source pixels. If it extends beyond the src bounds,
- // we cannot use the type-specific fast paths, as they access
- // the Pix fields directly without bounds checking.
- //
- // Similarly, the fast paths assume that the masks are nil.
- if o.SrcMask != nil || !sr.In(src.Bounds()) {
- z.scaleX_Image(tmp, src, sr, &o)
- } else {
- switch src := src.(type) {
- case *image.Gray:
- z.scaleX_Gray(tmp, src, sr, &o)
- case *image.NRGBA:
- z.scaleX_NRGBA(tmp, src, sr, &o)
- case *image.RGBA:
- z.scaleX_RGBA(tmp, src, sr, &o)
- case *image.YCbCr:
- switch src.SubsampleRatio {
- default:
- z.scaleX_Image(tmp, src, sr, &o)
- case image.YCbCrSubsampleRatio444:
- z.scaleX_YCbCr444(tmp, src, sr, &o)
- case image.YCbCrSubsampleRatio422:
- z.scaleX_YCbCr422(tmp, src, sr, &o)
- case image.YCbCrSubsampleRatio420:
- z.scaleX_YCbCr420(tmp, src, sr, &o)
- case image.YCbCrSubsampleRatio440:
- z.scaleX_YCbCr440(tmp, src, sr, &o)
- }
- default:
- z.scaleX_Image(tmp, src, sr, &o)
- }
- }
-
- if o.DstMask != nil {
- switch op {
- case Over:
- z.scaleY_Image_Over(dst, dr, adr, tmp, &o)
- case Src:
- z.scaleY_Image_Src(dst, dr, adr, tmp, &o)
- }
- } else {
- switch op {
- case Over:
- switch dst := dst.(type) {
- case *image.RGBA:
- z.scaleY_RGBA_Over(dst, dr, adr, tmp, &o)
- default:
- z.scaleY_Image_Over(dst, dr, adr, tmp, &o)
- }
- case Src:
- switch dst := dst.(type) {
- case *image.RGBA:
- z.scaleY_RGBA_Src(dst, dr, adr, tmp, &o)
- default:
- z.scaleY_Image_Src(dst, dr, adr, tmp, &o)
- }
- }
- }
-}
-
-func (q *Kernel) Transform(dst Image, s2d f64.Aff3, src image.Image, sr image.Rectangle, op Op, opts *Options) {
- var o Options
- if opts != nil {
- o = *opts
- }
-
- dr := transformRect(&s2d, &sr)
- // adr is the affected destination pixels.
- adr := dst.Bounds().Intersect(dr)
- adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
- if adr.Empty() || sr.Empty() {
- return
- }
- if op == Over && o.SrcMask == nil && opaque(src) {
- op = Src
- }
- d2s := invert(&s2d)
- // bias is a translation of the mapping from dst coordinates to src
- // coordinates such that the latter temporarily have non-negative X
- // and Y coordinates. This allows us to write int(f) instead of
- // int(math.Floor(f)), since "round to zero" and "round down" are
- // equivalent when f >= 0, but the former is much cheaper. The X--
- // and Y-- are because the TransformLeaf methods have a "sx -= 0.5"
- // adjustment.
- bias := transformRect(&d2s, &adr).Min
- bias.X--
- bias.Y--
- d2s[2] -= float64(bias.X)
- d2s[5] -= float64(bias.Y)
- // Make adr relative to dr.Min.
- adr = adr.Sub(dr.Min)
-
- if u, ok := src.(*image.Uniform); ok && o.DstMask != nil && o.SrcMask != nil && sr.In(src.Bounds()) {
- transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, op)
- return
- }
-
- xscale := abs(d2s[0])
- if s := abs(d2s[1]); xscale < s {
- xscale = s
- }
- yscale := abs(d2s[3])
- if s := abs(d2s[4]); yscale < s {
- yscale = s
- }
-
- // sr is the source pixels. If it extends beyond the src bounds,
- // we cannot use the type-specific fast paths, as they access
- // the Pix fields directly without bounds checking.
- //
- // Similarly, the fast paths assume that the masks are nil.
- if o.DstMask != nil || o.SrcMask != nil || !sr.In(src.Bounds()) {
- switch op {
- case Over:
- q.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
- case Src:
- q.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
- }
- } else {
- switch op {
- case Over:
- switch dst := dst.(type) {
- case *image.RGBA:
- switch src := src.(type) {
- case *image.NRGBA:
- q.transform_RGBA_NRGBA_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
- case *image.RGBA:
- q.transform_RGBA_RGBA_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
- default:
- q.transform_RGBA_Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
- }
- default:
- switch src := src.(type) {
- default:
- q.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
- }
- }
- case Src:
- switch dst := dst.(type) {
- case *image.RGBA:
- switch src := src.(type) {
- case *image.Gray:
- q.transform_RGBA_Gray_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
- case *image.NRGBA:
- q.transform_RGBA_NRGBA_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
- case *image.RGBA:
- q.transform_RGBA_RGBA_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
- case *image.YCbCr:
- switch src.SubsampleRatio {
- default:
- q.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
- case image.YCbCrSubsampleRatio444:
- q.transform_RGBA_YCbCr444_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
- case image.YCbCrSubsampleRatio422:
- q.transform_RGBA_YCbCr422_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
- case image.YCbCrSubsampleRatio420:
- q.transform_RGBA_YCbCr420_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
- case image.YCbCrSubsampleRatio440:
- q.transform_RGBA_YCbCr440_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
- }
- default:
- q.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
- }
- default:
- switch src := src.(type) {
- default:
- q.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
- }
- }
- }
- }
-}
-
-func (z *kernelScaler) scaleX_Gray(tmp [][4]float64, src *image.Gray, sr image.Rectangle, opts *Options) {
- t := 0
- for y := int32(0); y < z.sh; y++ {
- for _, s := range z.horizontal.sources {
- var pr float64
- for _, c := range z.horizontal.contribs[s.i:s.j] {
- pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
- pru := uint32(src.Pix[pi]) * 0x101
- pr += float64(pru) * c.weight
- }
- pr *= s.invTotalWeightFFFF
- tmp[t] = [4]float64{
- pr,
- pr,
- pr,
- 1,
- }
- t++
- }
- }
-}
-
-func (z *kernelScaler) scaleX_NRGBA(tmp [][4]float64, src *image.NRGBA, sr image.Rectangle, opts *Options) {
- t := 0
- for y := int32(0); y < z.sh; y++ {
- for _, s := range z.horizontal.sources {
- var pr, pg, pb, pa float64
- for _, c := range z.horizontal.contribs[s.i:s.j] {
- pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(c.coord)-src.Rect.Min.X)*4
- pau := uint32(src.Pix[pi+3]) * 0x101
- pru := uint32(src.Pix[pi+0]) * pau / 0xff
- pgu := uint32(src.Pix[pi+1]) * pau / 0xff
- pbu := uint32(src.Pix[pi+2]) * pau / 0xff
- pr += float64(pru) * c.weight
- pg += float64(pgu) * c.weight
- pb += float64(pbu) * c.weight
- pa += float64(pau) * c.weight
- }
- tmp[t] = [4]float64{
- pr * s.invTotalWeightFFFF,
- pg * s.invTotalWeightFFFF,
- pb * s.invTotalWeightFFFF,
- pa * s.invTotalWeightFFFF,
- }
- t++
- }
- }
-}
-
-func (z *kernelScaler) scaleX_RGBA(tmp [][4]float64, src *image.RGBA, sr image.Rectangle, opts *Options) {
- t := 0
- for y := int32(0); y < z.sh; y++ {
- for _, s := range z.horizontal.sources {
- var pr, pg, pb, pa float64
- for _, c := range z.horizontal.contribs[s.i:s.j] {
- pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(c.coord)-src.Rect.Min.X)*4
- pru := uint32(src.Pix[pi+0]) * 0x101
- pgu := uint32(src.Pix[pi+1]) * 0x101
- pbu := uint32(src.Pix[pi+2]) * 0x101
- pau := uint32(src.Pix[pi+3]) * 0x101
- pr += float64(pru) * c.weight
- pg += float64(pgu) * c.weight
- pb += float64(pbu) * c.weight
- pa += float64(pau) * c.weight
- }
- tmp[t] = [4]float64{
- pr * s.invTotalWeightFFFF,
- pg * s.invTotalWeightFFFF,
- pb * s.invTotalWeightFFFF,
- pa * s.invTotalWeightFFFF,
- }
- t++
- }
- }
-}
-
-func (z *kernelScaler) scaleX_YCbCr444(tmp [][4]float64, src *image.YCbCr, sr image.Rectangle, opts *Options) {
- t := 0
- for y := int32(0); y < z.sh; y++ {
- for _, s := range z.horizontal.sources {
- var pr, pg, pb float64
- for _, c := range z.horizontal.contribs[s.i:s.j] {
- pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
- pj := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10101
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pru := (pyy1 + 91881*pcr1) >> 8
- pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pbu := (pyy1 + 116130*pcb1) >> 8
- if pru < 0 {
- pru = 0
- } else if pru > 0xffff {
- pru = 0xffff
- }
- if pgu < 0 {
- pgu = 0
- } else if pgu > 0xffff {
- pgu = 0xffff
- }
- if pbu < 0 {
- pbu = 0
- } else if pbu > 0xffff {
- pbu = 0xffff
- }
-
- pr += float64(pru) * c.weight
- pg += float64(pgu) * c.weight
- pb += float64(pbu) * c.weight
- }
- tmp[t] = [4]float64{
- pr * s.invTotalWeightFFFF,
- pg * s.invTotalWeightFFFF,
- pb * s.invTotalWeightFFFF,
- 1,
- }
- t++
- }
- }
-}
-
-func (z *kernelScaler) scaleX_YCbCr422(tmp [][4]float64, src *image.YCbCr, sr image.Rectangle, opts *Options) {
- t := 0
- for y := int32(0); y < z.sh; y++ {
- for _, s := range z.horizontal.sources {
- var pr, pg, pb float64
- for _, c := range z.horizontal.contribs[s.i:s.j] {
- pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
- pj := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(c.coord))/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10101
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pru := (pyy1 + 91881*pcr1) >> 8
- pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pbu := (pyy1 + 116130*pcb1) >> 8
- if pru < 0 {
- pru = 0
- } else if pru > 0xffff {
- pru = 0xffff
- }
- if pgu < 0 {
- pgu = 0
- } else if pgu > 0xffff {
- pgu = 0xffff
- }
- if pbu < 0 {
- pbu = 0
- } else if pbu > 0xffff {
- pbu = 0xffff
- }
-
- pr += float64(pru) * c.weight
- pg += float64(pgu) * c.weight
- pb += float64(pbu) * c.weight
- }
- tmp[t] = [4]float64{
- pr * s.invTotalWeightFFFF,
- pg * s.invTotalWeightFFFF,
- pb * s.invTotalWeightFFFF,
- 1,
- }
- t++
- }
- }
-}
-
-func (z *kernelScaler) scaleX_YCbCr420(tmp [][4]float64, src *image.YCbCr, sr image.Rectangle, opts *Options) {
- t := 0
- for y := int32(0); y < z.sh; y++ {
- for _, s := range z.horizontal.sources {
- var pr, pg, pb float64
- for _, c := range z.horizontal.contribs[s.i:s.j] {
- pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
- pj := ((sr.Min.Y+int(y))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(c.coord))/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10101
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pru := (pyy1 + 91881*pcr1) >> 8
- pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pbu := (pyy1 + 116130*pcb1) >> 8
- if pru < 0 {
- pru = 0
- } else if pru > 0xffff {
- pru = 0xffff
- }
- if pgu < 0 {
- pgu = 0
- } else if pgu > 0xffff {
- pgu = 0xffff
- }
- if pbu < 0 {
- pbu = 0
- } else if pbu > 0xffff {
- pbu = 0xffff
- }
-
- pr += float64(pru) * c.weight
- pg += float64(pgu) * c.weight
- pb += float64(pbu) * c.weight
- }
- tmp[t] = [4]float64{
- pr * s.invTotalWeightFFFF,
- pg * s.invTotalWeightFFFF,
- pb * s.invTotalWeightFFFF,
- 1,
- }
- t++
- }
- }
-}
-
-func (z *kernelScaler) scaleX_YCbCr440(tmp [][4]float64, src *image.YCbCr, sr image.Rectangle, opts *Options) {
- t := 0
- for y := int32(0); y < z.sh; y++ {
- for _, s := range z.horizontal.sources {
- var pr, pg, pb float64
- for _, c := range z.horizontal.contribs[s.i:s.j] {
- pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
- pj := ((sr.Min.Y+int(y))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10101
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pru := (pyy1 + 91881*pcr1) >> 8
- pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pbu := (pyy1 + 116130*pcb1) >> 8
- if pru < 0 {
- pru = 0
- } else if pru > 0xffff {
- pru = 0xffff
- }
- if pgu < 0 {
- pgu = 0
- } else if pgu > 0xffff {
- pgu = 0xffff
- }
- if pbu < 0 {
- pbu = 0
- } else if pbu > 0xffff {
- pbu = 0xffff
- }
-
- pr += float64(pru) * c.weight
- pg += float64(pgu) * c.weight
- pb += float64(pbu) * c.weight
- }
- tmp[t] = [4]float64{
- pr * s.invTotalWeightFFFF,
- pg * s.invTotalWeightFFFF,
- pb * s.invTotalWeightFFFF,
- 1,
- }
- t++
- }
- }
-}
-
-func (z *kernelScaler) scaleX_Image(tmp [][4]float64, src image.Image, sr image.Rectangle, opts *Options) {
- t := 0
- srcMask, smp := opts.SrcMask, opts.SrcMaskP
- for y := int32(0); y < z.sh; y++ {
- for _, s := range z.horizontal.sources {
- var pr, pg, pb, pa float64
- for _, c := range z.horizontal.contribs[s.i:s.j] {
- pru, pgu, pbu, pau := src.At(sr.Min.X+int(c.coord), sr.Min.Y+int(y)).RGBA()
- if srcMask != nil {
- _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(c.coord), smp.Y+sr.Min.Y+int(y)).RGBA()
- pru = pru * ma / 0xffff
- pgu = pgu * ma / 0xffff
- pbu = pbu * ma / 0xffff
- pau = pau * ma / 0xffff
- }
- pr += float64(pru) * c.weight
- pg += float64(pgu) * c.weight
- pb += float64(pbu) * c.weight
- pa += float64(pau) * c.weight
- }
- tmp[t] = [4]float64{
- pr * s.invTotalWeightFFFF,
- pg * s.invTotalWeightFFFF,
- pb * s.invTotalWeightFFFF,
- pa * s.invTotalWeightFFFF,
- }
- t++
- }
- }
-}
-
-func (z *kernelScaler) scaleY_RGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, tmp [][4]float64, opts *Options) {
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
- d := (dr.Min.Y+adr.Min.Y-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+int(dx)-dst.Rect.Min.X)*4
- for _, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] {
- var pr, pg, pb, pa float64
- for _, c := range z.vertical.contribs[s.i:s.j] {
- p := &tmp[c.coord*z.dw+dx]
- pr += p[0] * c.weight
- pg += p[1] * c.weight
- pb += p[2] * c.weight
- pa += p[3] * c.weight
- }
-
- if pr > pa {
- pr = pa
- }
- if pg > pa {
- pg = pa
- }
- if pb > pa {
- pb = pa
- }
-
- pr0 := uint32(ftou(pr * s.invTotalWeight))
- pg0 := uint32(ftou(pg * s.invTotalWeight))
- pb0 := uint32(ftou(pb * s.invTotalWeight))
- pa0 := uint32(ftou(pa * s.invTotalWeight))
- pa1 := (0xffff - uint32(pa0)) * 0x101
- dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr0) >> 8)
- dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg0) >> 8)
- dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb0) >> 8)
- dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa0) >> 8)
- d += dst.Stride
- }
- }
-}
-
-func (z *kernelScaler) scaleY_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, tmp [][4]float64, opts *Options) {
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
- d := (dr.Min.Y+adr.Min.Y-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+int(dx)-dst.Rect.Min.X)*4
- for _, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] {
- var pr, pg, pb, pa float64
- for _, c := range z.vertical.contribs[s.i:s.j] {
- p := &tmp[c.coord*z.dw+dx]
- pr += p[0] * c.weight
- pg += p[1] * c.weight
- pb += p[2] * c.weight
- pa += p[3] * c.weight
- }
-
- if pr > pa {
- pr = pa
- }
- if pg > pa {
- pg = pa
- }
- if pb > pa {
- pb = pa
- }
-
- dst.Pix[d+0] = uint8(ftou(pr*s.invTotalWeight) >> 8)
- dst.Pix[d+1] = uint8(ftou(pg*s.invTotalWeight) >> 8)
- dst.Pix[d+2] = uint8(ftou(pb*s.invTotalWeight) >> 8)
- dst.Pix[d+3] = uint8(ftou(pa*s.invTotalWeight) >> 8)
- d += dst.Stride
- }
- }
-}
-
-func (z *kernelScaler) scaleY_Image_Over(dst Image, dr, adr image.Rectangle, tmp [][4]float64, opts *Options) {
- dstMask, dmp := opts.DstMask, opts.DstMaskP
- dstColorRGBA64 := &color.RGBA64{}
- dstColor := color.Color(dstColorRGBA64)
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
- for dy, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] {
- var pr, pg, pb, pa float64
- for _, c := range z.vertical.contribs[s.i:s.j] {
- p := &tmp[c.coord*z.dw+dx]
- pr += p[0] * c.weight
- pg += p[1] * c.weight
- pb += p[2] * c.weight
- pa += p[3] * c.weight
- }
-
- if pr > pa {
- pr = pa
- }
- if pg > pa {
- pg = pa
- }
- if pb > pa {
- pb = pa
- }
-
- qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy)).RGBA()
- pr0 := uint32(ftou(pr * s.invTotalWeight))
- pg0 := uint32(ftou(pg * s.invTotalWeight))
- pb0 := uint32(ftou(pb * s.invTotalWeight))
- pa0 := uint32(ftou(pa * s.invTotalWeight))
- if dstMask != nil {
- _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(adr.Min.Y+dy)).RGBA()
- pr0 = pr0 * ma / 0xffff
- pg0 = pg0 * ma / 0xffff
- pb0 = pb0 * ma / 0xffff
- pa0 = pa0 * ma / 0xffff
- }
- pa1 := 0xffff - pa0
- dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr0)
- dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg0)
- dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb0)
- dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa0)
- dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy), dstColor)
- }
- }
-}
-
-func (z *kernelScaler) scaleY_Image_Src(dst Image, dr, adr image.Rectangle, tmp [][4]float64, opts *Options) {
- dstMask, dmp := opts.DstMask, opts.DstMaskP
- dstColorRGBA64 := &color.RGBA64{}
- dstColor := color.Color(dstColorRGBA64)
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
- for dy, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] {
- var pr, pg, pb, pa float64
- for _, c := range z.vertical.contribs[s.i:s.j] {
- p := &tmp[c.coord*z.dw+dx]
- pr += p[0] * c.weight
- pg += p[1] * c.weight
- pb += p[2] * c.weight
- pa += p[3] * c.weight
- }
-
- if pr > pa {
- pr = pa
- }
- if pg > pa {
- pg = pa
- }
- if pb > pa {
- pb = pa
- }
-
- if dstMask != nil {
- qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy)).RGBA()
- _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(adr.Min.Y+dy)).RGBA()
- pr := uint32(ftou(pr*s.invTotalWeight)) * ma / 0xffff
- pg := uint32(ftou(pg*s.invTotalWeight)) * ma / 0xffff
- pb := uint32(ftou(pb*s.invTotalWeight)) * ma / 0xffff
- pa := uint32(ftou(pa*s.invTotalWeight)) * ma / 0xffff
- pa1 := 0xffff - ma
- dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
- dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
- dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
- dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
- dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy), dstColor)
- } else {
- dstColorRGBA64.R = ftou(pr * s.invTotalWeight)
- dstColorRGBA64.G = ftou(pg * s.invTotalWeight)
- dstColorRGBA64.B = ftou(pb * s.invTotalWeight)
- dstColorRGBA64.A = ftou(pa * s.invTotalWeight)
- dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy), dstColor)
- }
- }
- }
-}
-
-func (q *Kernel) transform_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.Gray, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
- // When shrinking, broaden the effective kernel support so that we still
- // visit every source pixel.
- xHalfWidth, xKernelArgScale := q.Support, 1.0
- if xscale > 1 {
- xHalfWidth *= xscale
- xKernelArgScale = 1 / xscale
- }
- yHalfWidth, yKernelArgScale := q.Support, 1.0
- if yscale > 1 {
- yHalfWidth *= yscale
- yKernelArgScale = 1 / yscale
- }
-
- xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
- yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- // TODO: adjust the bias so that we can use int(f) instead
- // of math.Floor(f) and math.Ceil(f).
- sx += float64(bias.X)
- sx -= 0.5
- ix := int(math.Floor(sx - xHalfWidth))
- if ix < sr.Min.X {
- ix = sr.Min.X
- }
- jx := int(math.Ceil(sx + xHalfWidth))
- if jx > sr.Max.X {
- jx = sr.Max.X
- }
-
- totalXWeight := 0.0
- for kx := ix; kx < jx; kx++ {
- xWeight := 0.0
- if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
- xWeight = q.At(t)
- }
- xWeights[kx-ix] = xWeight
- totalXWeight += xWeight
- }
- for x := range xWeights[:jx-ix] {
- xWeights[x] /= totalXWeight
- }
-
- sy += float64(bias.Y)
- sy -= 0.5
- iy := int(math.Floor(sy - yHalfWidth))
- if iy < sr.Min.Y {
- iy = sr.Min.Y
- }
- jy := int(math.Ceil(sy + yHalfWidth))
- if jy > sr.Max.Y {
- jy = sr.Max.Y
- }
-
- totalYWeight := 0.0
- for ky := iy; ky < jy; ky++ {
- yWeight := 0.0
- if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
- yWeight = q.At(t)
- }
- yWeights[ky-iy] = yWeight
- totalYWeight += yWeight
- }
- for y := range yWeights[:jy-iy] {
- yWeights[y] /= totalYWeight
- }
-
- var pr float64
- for ky := iy; ky < jy; ky++ {
- if yWeight := yWeights[ky-iy]; yWeight != 0 {
- for kx := ix; kx < jx; kx++ {
- if w := xWeights[kx-ix] * yWeight; w != 0 {
- pi := (ky-src.Rect.Min.Y)*src.Stride + (kx - src.Rect.Min.X)
- pru := uint32(src.Pix[pi]) * 0x101
- pr += float64(pru) * w
- }
- }
- }
- }
- out := uint8(fffftou(pr) >> 8)
- dst.Pix[d+0] = out
- dst.Pix[d+1] = out
- dst.Pix[d+2] = out
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (q *Kernel) transform_RGBA_NRGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.NRGBA, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
- // When shrinking, broaden the effective kernel support so that we still
- // visit every source pixel.
- xHalfWidth, xKernelArgScale := q.Support, 1.0
- if xscale > 1 {
- xHalfWidth *= xscale
- xKernelArgScale = 1 / xscale
- }
- yHalfWidth, yKernelArgScale := q.Support, 1.0
- if yscale > 1 {
- yHalfWidth *= yscale
- yKernelArgScale = 1 / yscale
- }
-
- xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
- yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- // TODO: adjust the bias so that we can use int(f) instead
- // of math.Floor(f) and math.Ceil(f).
- sx += float64(bias.X)
- sx -= 0.5
- ix := int(math.Floor(sx - xHalfWidth))
- if ix < sr.Min.X {
- ix = sr.Min.X
- }
- jx := int(math.Ceil(sx + xHalfWidth))
- if jx > sr.Max.X {
- jx = sr.Max.X
- }
-
- totalXWeight := 0.0
- for kx := ix; kx < jx; kx++ {
- xWeight := 0.0
- if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
- xWeight = q.At(t)
- }
- xWeights[kx-ix] = xWeight
- totalXWeight += xWeight
- }
- for x := range xWeights[:jx-ix] {
- xWeights[x] /= totalXWeight
- }
-
- sy += float64(bias.Y)
- sy -= 0.5
- iy := int(math.Floor(sy - yHalfWidth))
- if iy < sr.Min.Y {
- iy = sr.Min.Y
- }
- jy := int(math.Ceil(sy + yHalfWidth))
- if jy > sr.Max.Y {
- jy = sr.Max.Y
- }
-
- totalYWeight := 0.0
- for ky := iy; ky < jy; ky++ {
- yWeight := 0.0
- if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
- yWeight = q.At(t)
- }
- yWeights[ky-iy] = yWeight
- totalYWeight += yWeight
- }
- for y := range yWeights[:jy-iy] {
- yWeights[y] /= totalYWeight
- }
-
- var pr, pg, pb, pa float64
- for ky := iy; ky < jy; ky++ {
- if yWeight := yWeights[ky-iy]; yWeight != 0 {
- for kx := ix; kx < jx; kx++ {
- if w := xWeights[kx-ix] * yWeight; w != 0 {
- pi := (ky-src.Rect.Min.Y)*src.Stride + (kx-src.Rect.Min.X)*4
- pau := uint32(src.Pix[pi+3]) * 0x101
- pru := uint32(src.Pix[pi+0]) * pau / 0xff
- pgu := uint32(src.Pix[pi+1]) * pau / 0xff
- pbu := uint32(src.Pix[pi+2]) * pau / 0xff
- pr += float64(pru) * w
- pg += float64(pgu) * w
- pb += float64(pbu) * w
- pa += float64(pau) * w
- }
- }
- }
- }
-
- if pr > pa {
- pr = pa
- }
- if pg > pa {
- pg = pa
- }
- if pb > pa {
- pb = pa
- }
-
- pr0 := uint32(fffftou(pr))
- pg0 := uint32(fffftou(pg))
- pb0 := uint32(fffftou(pb))
- pa0 := uint32(fffftou(pa))
- pa1 := (0xffff - uint32(pa0)) * 0x101
- dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr0) >> 8)
- dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg0) >> 8)
- dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb0) >> 8)
- dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa0) >> 8)
- }
- }
-}
-
-func (q *Kernel) transform_RGBA_NRGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.NRGBA, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
- // When shrinking, broaden the effective kernel support so that we still
- // visit every source pixel.
- xHalfWidth, xKernelArgScale := q.Support, 1.0
- if xscale > 1 {
- xHalfWidth *= xscale
- xKernelArgScale = 1 / xscale
- }
- yHalfWidth, yKernelArgScale := q.Support, 1.0
- if yscale > 1 {
- yHalfWidth *= yscale
- yKernelArgScale = 1 / yscale
- }
-
- xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
- yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- // TODO: adjust the bias so that we can use int(f) instead
- // of math.Floor(f) and math.Ceil(f).
- sx += float64(bias.X)
- sx -= 0.5
- ix := int(math.Floor(sx - xHalfWidth))
- if ix < sr.Min.X {
- ix = sr.Min.X
- }
- jx := int(math.Ceil(sx + xHalfWidth))
- if jx > sr.Max.X {
- jx = sr.Max.X
- }
-
- totalXWeight := 0.0
- for kx := ix; kx < jx; kx++ {
- xWeight := 0.0
- if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
- xWeight = q.At(t)
- }
- xWeights[kx-ix] = xWeight
- totalXWeight += xWeight
- }
- for x := range xWeights[:jx-ix] {
- xWeights[x] /= totalXWeight
- }
-
- sy += float64(bias.Y)
- sy -= 0.5
- iy := int(math.Floor(sy - yHalfWidth))
- if iy < sr.Min.Y {
- iy = sr.Min.Y
- }
- jy := int(math.Ceil(sy + yHalfWidth))
- if jy > sr.Max.Y {
- jy = sr.Max.Y
- }
-
- totalYWeight := 0.0
- for ky := iy; ky < jy; ky++ {
- yWeight := 0.0
- if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
- yWeight = q.At(t)
- }
- yWeights[ky-iy] = yWeight
- totalYWeight += yWeight
- }
- for y := range yWeights[:jy-iy] {
- yWeights[y] /= totalYWeight
- }
-
- var pr, pg, pb, pa float64
- for ky := iy; ky < jy; ky++ {
- if yWeight := yWeights[ky-iy]; yWeight != 0 {
- for kx := ix; kx < jx; kx++ {
- if w := xWeights[kx-ix] * yWeight; w != 0 {
- pi := (ky-src.Rect.Min.Y)*src.Stride + (kx-src.Rect.Min.X)*4
- pau := uint32(src.Pix[pi+3]) * 0x101
- pru := uint32(src.Pix[pi+0]) * pau / 0xff
- pgu := uint32(src.Pix[pi+1]) * pau / 0xff
- pbu := uint32(src.Pix[pi+2]) * pau / 0xff
- pr += float64(pru) * w
- pg += float64(pgu) * w
- pb += float64(pbu) * w
- pa += float64(pau) * w
- }
- }
- }
- }
-
- if pr > pa {
- pr = pa
- }
- if pg > pa {
- pg = pa
- }
- if pb > pa {
- pb = pa
- }
-
- dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
- dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
- dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
- dst.Pix[d+3] = uint8(fffftou(pa) >> 8)
- }
- }
-}
-
-func (q *Kernel) transform_RGBA_RGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.RGBA, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
- // When shrinking, broaden the effective kernel support so that we still
- // visit every source pixel.
- xHalfWidth, xKernelArgScale := q.Support, 1.0
- if xscale > 1 {
- xHalfWidth *= xscale
- xKernelArgScale = 1 / xscale
- }
- yHalfWidth, yKernelArgScale := q.Support, 1.0
- if yscale > 1 {
- yHalfWidth *= yscale
- yKernelArgScale = 1 / yscale
- }
-
- xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
- yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- // TODO: adjust the bias so that we can use int(f) instead
- // of math.Floor(f) and math.Ceil(f).
- sx += float64(bias.X)
- sx -= 0.5
- ix := int(math.Floor(sx - xHalfWidth))
- if ix < sr.Min.X {
- ix = sr.Min.X
- }
- jx := int(math.Ceil(sx + xHalfWidth))
- if jx > sr.Max.X {
- jx = sr.Max.X
- }
-
- totalXWeight := 0.0
- for kx := ix; kx < jx; kx++ {
- xWeight := 0.0
- if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
- xWeight = q.At(t)
- }
- xWeights[kx-ix] = xWeight
- totalXWeight += xWeight
- }
- for x := range xWeights[:jx-ix] {
- xWeights[x] /= totalXWeight
- }
-
- sy += float64(bias.Y)
- sy -= 0.5
- iy := int(math.Floor(sy - yHalfWidth))
- if iy < sr.Min.Y {
- iy = sr.Min.Y
- }
- jy := int(math.Ceil(sy + yHalfWidth))
- if jy > sr.Max.Y {
- jy = sr.Max.Y
- }
-
- totalYWeight := 0.0
- for ky := iy; ky < jy; ky++ {
- yWeight := 0.0
- if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
- yWeight = q.At(t)
- }
- yWeights[ky-iy] = yWeight
- totalYWeight += yWeight
- }
- for y := range yWeights[:jy-iy] {
- yWeights[y] /= totalYWeight
- }
-
- var pr, pg, pb, pa float64
- for ky := iy; ky < jy; ky++ {
- if yWeight := yWeights[ky-iy]; yWeight != 0 {
- for kx := ix; kx < jx; kx++ {
- if w := xWeights[kx-ix] * yWeight; w != 0 {
- pi := (ky-src.Rect.Min.Y)*src.Stride + (kx-src.Rect.Min.X)*4
- pru := uint32(src.Pix[pi+0]) * 0x101
- pgu := uint32(src.Pix[pi+1]) * 0x101
- pbu := uint32(src.Pix[pi+2]) * 0x101
- pau := uint32(src.Pix[pi+3]) * 0x101
- pr += float64(pru) * w
- pg += float64(pgu) * w
- pb += float64(pbu) * w
- pa += float64(pau) * w
- }
- }
- }
- }
-
- if pr > pa {
- pr = pa
- }
- if pg > pa {
- pg = pa
- }
- if pb > pa {
- pb = pa
- }
-
- pr0 := uint32(fffftou(pr))
- pg0 := uint32(fffftou(pg))
- pb0 := uint32(fffftou(pb))
- pa0 := uint32(fffftou(pa))
- pa1 := (0xffff - uint32(pa0)) * 0x101
- dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr0) >> 8)
- dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg0) >> 8)
- dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb0) >> 8)
- dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa0) >> 8)
- }
- }
-}
-
-func (q *Kernel) transform_RGBA_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.RGBA, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
- // When shrinking, broaden the effective kernel support so that we still
- // visit every source pixel.
- xHalfWidth, xKernelArgScale := q.Support, 1.0
- if xscale > 1 {
- xHalfWidth *= xscale
- xKernelArgScale = 1 / xscale
- }
- yHalfWidth, yKernelArgScale := q.Support, 1.0
- if yscale > 1 {
- yHalfWidth *= yscale
- yKernelArgScale = 1 / yscale
- }
-
- xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
- yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- // TODO: adjust the bias so that we can use int(f) instead
- // of math.Floor(f) and math.Ceil(f).
- sx += float64(bias.X)
- sx -= 0.5
- ix := int(math.Floor(sx - xHalfWidth))
- if ix < sr.Min.X {
- ix = sr.Min.X
- }
- jx := int(math.Ceil(sx + xHalfWidth))
- if jx > sr.Max.X {
- jx = sr.Max.X
- }
-
- totalXWeight := 0.0
- for kx := ix; kx < jx; kx++ {
- xWeight := 0.0
- if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
- xWeight = q.At(t)
- }
- xWeights[kx-ix] = xWeight
- totalXWeight += xWeight
- }
- for x := range xWeights[:jx-ix] {
- xWeights[x] /= totalXWeight
- }
-
- sy += float64(bias.Y)
- sy -= 0.5
- iy := int(math.Floor(sy - yHalfWidth))
- if iy < sr.Min.Y {
- iy = sr.Min.Y
- }
- jy := int(math.Ceil(sy + yHalfWidth))
- if jy > sr.Max.Y {
- jy = sr.Max.Y
- }
-
- totalYWeight := 0.0
- for ky := iy; ky < jy; ky++ {
- yWeight := 0.0
- if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
- yWeight = q.At(t)
- }
- yWeights[ky-iy] = yWeight
- totalYWeight += yWeight
- }
- for y := range yWeights[:jy-iy] {
- yWeights[y] /= totalYWeight
- }
-
- var pr, pg, pb, pa float64
- for ky := iy; ky < jy; ky++ {
- if yWeight := yWeights[ky-iy]; yWeight != 0 {
- for kx := ix; kx < jx; kx++ {
- if w := xWeights[kx-ix] * yWeight; w != 0 {
- pi := (ky-src.Rect.Min.Y)*src.Stride + (kx-src.Rect.Min.X)*4
- pru := uint32(src.Pix[pi+0]) * 0x101
- pgu := uint32(src.Pix[pi+1]) * 0x101
- pbu := uint32(src.Pix[pi+2]) * 0x101
- pau := uint32(src.Pix[pi+3]) * 0x101
- pr += float64(pru) * w
- pg += float64(pgu) * w
- pb += float64(pbu) * w
- pa += float64(pau) * w
- }
- }
- }
- }
-
- if pr > pa {
- pr = pa
- }
- if pg > pa {
- pg = pa
- }
- if pb > pa {
- pb = pa
- }
-
- dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
- dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
- dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
- dst.Pix[d+3] = uint8(fffftou(pa) >> 8)
- }
- }
-}
-
-func (q *Kernel) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
- // When shrinking, broaden the effective kernel support so that we still
- // visit every source pixel.
- xHalfWidth, xKernelArgScale := q.Support, 1.0
- if xscale > 1 {
- xHalfWidth *= xscale
- xKernelArgScale = 1 / xscale
- }
- yHalfWidth, yKernelArgScale := q.Support, 1.0
- if yscale > 1 {
- yHalfWidth *= yscale
- yKernelArgScale = 1 / yscale
- }
-
- xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
- yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- // TODO: adjust the bias so that we can use int(f) instead
- // of math.Floor(f) and math.Ceil(f).
- sx += float64(bias.X)
- sx -= 0.5
- ix := int(math.Floor(sx - xHalfWidth))
- if ix < sr.Min.X {
- ix = sr.Min.X
- }
- jx := int(math.Ceil(sx + xHalfWidth))
- if jx > sr.Max.X {
- jx = sr.Max.X
- }
-
- totalXWeight := 0.0
- for kx := ix; kx < jx; kx++ {
- xWeight := 0.0
- if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
- xWeight = q.At(t)
- }
- xWeights[kx-ix] = xWeight
- totalXWeight += xWeight
- }
- for x := range xWeights[:jx-ix] {
- xWeights[x] /= totalXWeight
- }
-
- sy += float64(bias.Y)
- sy -= 0.5
- iy := int(math.Floor(sy - yHalfWidth))
- if iy < sr.Min.Y {
- iy = sr.Min.Y
- }
- jy := int(math.Ceil(sy + yHalfWidth))
- if jy > sr.Max.Y {
- jy = sr.Max.Y
- }
-
- totalYWeight := 0.0
- for ky := iy; ky < jy; ky++ {
- yWeight := 0.0
- if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
- yWeight = q.At(t)
- }
- yWeights[ky-iy] = yWeight
- totalYWeight += yWeight
- }
- for y := range yWeights[:jy-iy] {
- yWeights[y] /= totalYWeight
- }
-
- var pr, pg, pb float64
- for ky := iy; ky < jy; ky++ {
- if yWeight := yWeights[ky-iy]; yWeight != 0 {
- for kx := ix; kx < jx; kx++ {
- if w := xWeights[kx-ix] * yWeight; w != 0 {
- pi := (ky-src.Rect.Min.Y)*src.YStride + (kx - src.Rect.Min.X)
- pj := (ky-src.Rect.Min.Y)*src.CStride + (kx - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10101
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pru := (pyy1 + 91881*pcr1) >> 8
- pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pbu := (pyy1 + 116130*pcb1) >> 8
- if pru < 0 {
- pru = 0
- } else if pru > 0xffff {
- pru = 0xffff
- }
- if pgu < 0 {
- pgu = 0
- } else if pgu > 0xffff {
- pgu = 0xffff
- }
- if pbu < 0 {
- pbu = 0
- } else if pbu > 0xffff {
- pbu = 0xffff
- }
-
- pr += float64(pru) * w
- pg += float64(pgu) * w
- pb += float64(pbu) * w
- }
- }
- }
- }
- dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
- dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
- dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (q *Kernel) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
- // When shrinking, broaden the effective kernel support so that we still
- // visit every source pixel.
- xHalfWidth, xKernelArgScale := q.Support, 1.0
- if xscale > 1 {
- xHalfWidth *= xscale
- xKernelArgScale = 1 / xscale
- }
- yHalfWidth, yKernelArgScale := q.Support, 1.0
- if yscale > 1 {
- yHalfWidth *= yscale
- yKernelArgScale = 1 / yscale
- }
-
- xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
- yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- // TODO: adjust the bias so that we can use int(f) instead
- // of math.Floor(f) and math.Ceil(f).
- sx += float64(bias.X)
- sx -= 0.5
- ix := int(math.Floor(sx - xHalfWidth))
- if ix < sr.Min.X {
- ix = sr.Min.X
- }
- jx := int(math.Ceil(sx + xHalfWidth))
- if jx > sr.Max.X {
- jx = sr.Max.X
- }
-
- totalXWeight := 0.0
- for kx := ix; kx < jx; kx++ {
- xWeight := 0.0
- if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
- xWeight = q.At(t)
- }
- xWeights[kx-ix] = xWeight
- totalXWeight += xWeight
- }
- for x := range xWeights[:jx-ix] {
- xWeights[x] /= totalXWeight
- }
-
- sy += float64(bias.Y)
- sy -= 0.5
- iy := int(math.Floor(sy - yHalfWidth))
- if iy < sr.Min.Y {
- iy = sr.Min.Y
- }
- jy := int(math.Ceil(sy + yHalfWidth))
- if jy > sr.Max.Y {
- jy = sr.Max.Y
- }
-
- totalYWeight := 0.0
- for ky := iy; ky < jy; ky++ {
- yWeight := 0.0
- if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
- yWeight = q.At(t)
- }
- yWeights[ky-iy] = yWeight
- totalYWeight += yWeight
- }
- for y := range yWeights[:jy-iy] {
- yWeights[y] /= totalYWeight
- }
-
- var pr, pg, pb float64
- for ky := iy; ky < jy; ky++ {
- if yWeight := yWeights[ky-iy]; yWeight != 0 {
- for kx := ix; kx < jx; kx++ {
- if w := xWeights[kx-ix] * yWeight; w != 0 {
- pi := (ky-src.Rect.Min.Y)*src.YStride + (kx - src.Rect.Min.X)
- pj := (ky-src.Rect.Min.Y)*src.CStride + ((kx)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10101
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pru := (pyy1 + 91881*pcr1) >> 8
- pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pbu := (pyy1 + 116130*pcb1) >> 8
- if pru < 0 {
- pru = 0
- } else if pru > 0xffff {
- pru = 0xffff
- }
- if pgu < 0 {
- pgu = 0
- } else if pgu > 0xffff {
- pgu = 0xffff
- }
- if pbu < 0 {
- pbu = 0
- } else if pbu > 0xffff {
- pbu = 0xffff
- }
-
- pr += float64(pru) * w
- pg += float64(pgu) * w
- pb += float64(pbu) * w
- }
- }
- }
- }
- dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
- dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
- dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (q *Kernel) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
- // When shrinking, broaden the effective kernel support so that we still
- // visit every source pixel.
- xHalfWidth, xKernelArgScale := q.Support, 1.0
- if xscale > 1 {
- xHalfWidth *= xscale
- xKernelArgScale = 1 / xscale
- }
- yHalfWidth, yKernelArgScale := q.Support, 1.0
- if yscale > 1 {
- yHalfWidth *= yscale
- yKernelArgScale = 1 / yscale
- }
-
- xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
- yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- // TODO: adjust the bias so that we can use int(f) instead
- // of math.Floor(f) and math.Ceil(f).
- sx += float64(bias.X)
- sx -= 0.5
- ix := int(math.Floor(sx - xHalfWidth))
- if ix < sr.Min.X {
- ix = sr.Min.X
- }
- jx := int(math.Ceil(sx + xHalfWidth))
- if jx > sr.Max.X {
- jx = sr.Max.X
- }
-
- totalXWeight := 0.0
- for kx := ix; kx < jx; kx++ {
- xWeight := 0.0
- if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
- xWeight = q.At(t)
- }
- xWeights[kx-ix] = xWeight
- totalXWeight += xWeight
- }
- for x := range xWeights[:jx-ix] {
- xWeights[x] /= totalXWeight
- }
-
- sy += float64(bias.Y)
- sy -= 0.5
- iy := int(math.Floor(sy - yHalfWidth))
- if iy < sr.Min.Y {
- iy = sr.Min.Y
- }
- jy := int(math.Ceil(sy + yHalfWidth))
- if jy > sr.Max.Y {
- jy = sr.Max.Y
- }
-
- totalYWeight := 0.0
- for ky := iy; ky < jy; ky++ {
- yWeight := 0.0
- if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
- yWeight = q.At(t)
- }
- yWeights[ky-iy] = yWeight
- totalYWeight += yWeight
- }
- for y := range yWeights[:jy-iy] {
- yWeights[y] /= totalYWeight
- }
-
- var pr, pg, pb float64
- for ky := iy; ky < jy; ky++ {
- if yWeight := yWeights[ky-iy]; yWeight != 0 {
- for kx := ix; kx < jx; kx++ {
- if w := xWeights[kx-ix] * yWeight; w != 0 {
- pi := (ky-src.Rect.Min.Y)*src.YStride + (kx - src.Rect.Min.X)
- pj := ((ky)/2-src.Rect.Min.Y/2)*src.CStride + ((kx)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10101
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pru := (pyy1 + 91881*pcr1) >> 8
- pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pbu := (pyy1 + 116130*pcb1) >> 8
- if pru < 0 {
- pru = 0
- } else if pru > 0xffff {
- pru = 0xffff
- }
- if pgu < 0 {
- pgu = 0
- } else if pgu > 0xffff {
- pgu = 0xffff
- }
- if pbu < 0 {
- pbu = 0
- } else if pbu > 0xffff {
- pbu = 0xffff
- }
-
- pr += float64(pru) * w
- pg += float64(pgu) * w
- pb += float64(pbu) * w
- }
- }
- }
- }
- dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
- dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
- dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (q *Kernel) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
- // When shrinking, broaden the effective kernel support so that we still
- // visit every source pixel.
- xHalfWidth, xKernelArgScale := q.Support, 1.0
- if xscale > 1 {
- xHalfWidth *= xscale
- xKernelArgScale = 1 / xscale
- }
- yHalfWidth, yKernelArgScale := q.Support, 1.0
- if yscale > 1 {
- yHalfWidth *= yscale
- yKernelArgScale = 1 / yscale
- }
-
- xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
- yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- // TODO: adjust the bias so that we can use int(f) instead
- // of math.Floor(f) and math.Ceil(f).
- sx += float64(bias.X)
- sx -= 0.5
- ix := int(math.Floor(sx - xHalfWidth))
- if ix < sr.Min.X {
- ix = sr.Min.X
- }
- jx := int(math.Ceil(sx + xHalfWidth))
- if jx > sr.Max.X {
- jx = sr.Max.X
- }
-
- totalXWeight := 0.0
- for kx := ix; kx < jx; kx++ {
- xWeight := 0.0
- if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
- xWeight = q.At(t)
- }
- xWeights[kx-ix] = xWeight
- totalXWeight += xWeight
- }
- for x := range xWeights[:jx-ix] {
- xWeights[x] /= totalXWeight
- }
-
- sy += float64(bias.Y)
- sy -= 0.5
- iy := int(math.Floor(sy - yHalfWidth))
- if iy < sr.Min.Y {
- iy = sr.Min.Y
- }
- jy := int(math.Ceil(sy + yHalfWidth))
- if jy > sr.Max.Y {
- jy = sr.Max.Y
- }
-
- totalYWeight := 0.0
- for ky := iy; ky < jy; ky++ {
- yWeight := 0.0
- if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
- yWeight = q.At(t)
- }
- yWeights[ky-iy] = yWeight
- totalYWeight += yWeight
- }
- for y := range yWeights[:jy-iy] {
- yWeights[y] /= totalYWeight
- }
-
- var pr, pg, pb float64
- for ky := iy; ky < jy; ky++ {
- if yWeight := yWeights[ky-iy]; yWeight != 0 {
- for kx := ix; kx < jx; kx++ {
- if w := xWeights[kx-ix] * yWeight; w != 0 {
- pi := (ky-src.Rect.Min.Y)*src.YStride + (kx - src.Rect.Min.X)
- pj := ((ky)/2-src.Rect.Min.Y/2)*src.CStride + (kx - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi]) * 0x10101
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pru := (pyy1 + 91881*pcr1) >> 8
- pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pbu := (pyy1 + 116130*pcb1) >> 8
- if pru < 0 {
- pru = 0
- } else if pru > 0xffff {
- pru = 0xffff
- }
- if pgu < 0 {
- pgu = 0
- } else if pgu > 0xffff {
- pgu = 0xffff
- }
- if pbu < 0 {
- pbu = 0
- } else if pbu > 0xffff {
- pbu = 0xffff
- }
-
- pr += float64(pru) * w
- pg += float64(pgu) * w
- pb += float64(pbu) * w
- }
- }
- }
- }
- dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
- dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
- dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (q *Kernel) transform_RGBA_Image_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
- // When shrinking, broaden the effective kernel support so that we still
- // visit every source pixel.
- xHalfWidth, xKernelArgScale := q.Support, 1.0
- if xscale > 1 {
- xHalfWidth *= xscale
- xKernelArgScale = 1 / xscale
- }
- yHalfWidth, yKernelArgScale := q.Support, 1.0
- if yscale > 1 {
- yHalfWidth *= yscale
- yKernelArgScale = 1 / yscale
- }
-
- xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
- yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- // TODO: adjust the bias so that we can use int(f) instead
- // of math.Floor(f) and math.Ceil(f).
- sx += float64(bias.X)
- sx -= 0.5
- ix := int(math.Floor(sx - xHalfWidth))
- if ix < sr.Min.X {
- ix = sr.Min.X
- }
- jx := int(math.Ceil(sx + xHalfWidth))
- if jx > sr.Max.X {
- jx = sr.Max.X
- }
-
- totalXWeight := 0.0
- for kx := ix; kx < jx; kx++ {
- xWeight := 0.0
- if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
- xWeight = q.At(t)
- }
- xWeights[kx-ix] = xWeight
- totalXWeight += xWeight
- }
- for x := range xWeights[:jx-ix] {
- xWeights[x] /= totalXWeight
- }
-
- sy += float64(bias.Y)
- sy -= 0.5
- iy := int(math.Floor(sy - yHalfWidth))
- if iy < sr.Min.Y {
- iy = sr.Min.Y
- }
- jy := int(math.Ceil(sy + yHalfWidth))
- if jy > sr.Max.Y {
- jy = sr.Max.Y
- }
-
- totalYWeight := 0.0
- for ky := iy; ky < jy; ky++ {
- yWeight := 0.0
- if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
- yWeight = q.At(t)
- }
- yWeights[ky-iy] = yWeight
- totalYWeight += yWeight
- }
- for y := range yWeights[:jy-iy] {
- yWeights[y] /= totalYWeight
- }
-
- var pr, pg, pb, pa float64
- for ky := iy; ky < jy; ky++ {
- if yWeight := yWeights[ky-iy]; yWeight != 0 {
- for kx := ix; kx < jx; kx++ {
- if w := xWeights[kx-ix] * yWeight; w != 0 {
- pru, pgu, pbu, pau := src.At(kx, ky).RGBA()
- pr += float64(pru) * w
- pg += float64(pgu) * w
- pb += float64(pbu) * w
- pa += float64(pau) * w
- }
- }
- }
- }
-
- if pr > pa {
- pr = pa
- }
- if pg > pa {
- pg = pa
- }
- if pb > pa {
- pb = pa
- }
-
- pr0 := uint32(fffftou(pr))
- pg0 := uint32(fffftou(pg))
- pb0 := uint32(fffftou(pb))
- pa0 := uint32(fffftou(pa))
- pa1 := (0xffff - uint32(pa0)) * 0x101
- dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr0) >> 8)
- dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg0) >> 8)
- dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb0) >> 8)
- dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa0) >> 8)
- }
- }
-}
-
-func (q *Kernel) transform_RGBA_Image_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
- // When shrinking, broaden the effective kernel support so that we still
- // visit every source pixel.
- xHalfWidth, xKernelArgScale := q.Support, 1.0
- if xscale > 1 {
- xHalfWidth *= xscale
- xKernelArgScale = 1 / xscale
- }
- yHalfWidth, yKernelArgScale := q.Support, 1.0
- if yscale > 1 {
- yHalfWidth *= yscale
- yKernelArgScale = 1 / yscale
- }
-
- xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
- yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- // TODO: adjust the bias so that we can use int(f) instead
- // of math.Floor(f) and math.Ceil(f).
- sx += float64(bias.X)
- sx -= 0.5
- ix := int(math.Floor(sx - xHalfWidth))
- if ix < sr.Min.X {
- ix = sr.Min.X
- }
- jx := int(math.Ceil(sx + xHalfWidth))
- if jx > sr.Max.X {
- jx = sr.Max.X
- }
-
- totalXWeight := 0.0
- for kx := ix; kx < jx; kx++ {
- xWeight := 0.0
- if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
- xWeight = q.At(t)
- }
- xWeights[kx-ix] = xWeight
- totalXWeight += xWeight
- }
- for x := range xWeights[:jx-ix] {
- xWeights[x] /= totalXWeight
- }
-
- sy += float64(bias.Y)
- sy -= 0.5
- iy := int(math.Floor(sy - yHalfWidth))
- if iy < sr.Min.Y {
- iy = sr.Min.Y
- }
- jy := int(math.Ceil(sy + yHalfWidth))
- if jy > sr.Max.Y {
- jy = sr.Max.Y
- }
-
- totalYWeight := 0.0
- for ky := iy; ky < jy; ky++ {
- yWeight := 0.0
- if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
- yWeight = q.At(t)
- }
- yWeights[ky-iy] = yWeight
- totalYWeight += yWeight
- }
- for y := range yWeights[:jy-iy] {
- yWeights[y] /= totalYWeight
- }
-
- var pr, pg, pb, pa float64
- for ky := iy; ky < jy; ky++ {
- if yWeight := yWeights[ky-iy]; yWeight != 0 {
- for kx := ix; kx < jx; kx++ {
- if w := xWeights[kx-ix] * yWeight; w != 0 {
- pru, pgu, pbu, pau := src.At(kx, ky).RGBA()
- pr += float64(pru) * w
- pg += float64(pgu) * w
- pb += float64(pbu) * w
- pa += float64(pau) * w
- }
- }
- }
- }
-
- if pr > pa {
- pr = pa
- }
- if pg > pa {
- pg = pa
- }
- if pb > pa {
- pb = pa
- }
-
- dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
- dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
- dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
- dst.Pix[d+3] = uint8(fffftou(pa) >> 8)
- }
- }
-}
-
-func (q *Kernel) transform_Image_Image_Over(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
- // When shrinking, broaden the effective kernel support so that we still
- // visit every source pixel.
- xHalfWidth, xKernelArgScale := q.Support, 1.0
- if xscale > 1 {
- xHalfWidth *= xscale
- xKernelArgScale = 1 / xscale
- }
- yHalfWidth, yKernelArgScale := q.Support, 1.0
- if yscale > 1 {
- yHalfWidth *= yscale
- yKernelArgScale = 1 / yscale
- }
-
- xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
- yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
-
- srcMask, smp := opts.SrcMask, opts.SrcMaskP
- dstMask, dmp := opts.DstMask, opts.DstMaskP
- dstColorRGBA64 := &color.RGBA64{}
- dstColor := color.Color(dstColorRGBA64)
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- // TODO: adjust the bias so that we can use int(f) instead
- // of math.Floor(f) and math.Ceil(f).
- sx += float64(bias.X)
- sx -= 0.5
- ix := int(math.Floor(sx - xHalfWidth))
- if ix < sr.Min.X {
- ix = sr.Min.X
- }
- jx := int(math.Ceil(sx + xHalfWidth))
- if jx > sr.Max.X {
- jx = sr.Max.X
- }
-
- totalXWeight := 0.0
- for kx := ix; kx < jx; kx++ {
- xWeight := 0.0
- if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
- xWeight = q.At(t)
- }
- xWeights[kx-ix] = xWeight
- totalXWeight += xWeight
- }
- for x := range xWeights[:jx-ix] {
- xWeights[x] /= totalXWeight
- }
-
- sy += float64(bias.Y)
- sy -= 0.5
- iy := int(math.Floor(sy - yHalfWidth))
- if iy < sr.Min.Y {
- iy = sr.Min.Y
- }
- jy := int(math.Ceil(sy + yHalfWidth))
- if jy > sr.Max.Y {
- jy = sr.Max.Y
- }
-
- totalYWeight := 0.0
- for ky := iy; ky < jy; ky++ {
- yWeight := 0.0
- if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
- yWeight = q.At(t)
- }
- yWeights[ky-iy] = yWeight
- totalYWeight += yWeight
- }
- for y := range yWeights[:jy-iy] {
- yWeights[y] /= totalYWeight
- }
-
- var pr, pg, pb, pa float64
- for ky := iy; ky < jy; ky++ {
- if yWeight := yWeights[ky-iy]; yWeight != 0 {
- for kx := ix; kx < jx; kx++ {
- if w := xWeights[kx-ix] * yWeight; w != 0 {
- pru, pgu, pbu, pau := src.At(kx, ky).RGBA()
- if srcMask != nil {
- _, _, _, ma := srcMask.At(smp.X+kx, smp.Y+ky).RGBA()
- pru = pru * ma / 0xffff
- pgu = pgu * ma / 0xffff
- pbu = pbu * ma / 0xffff
- pau = pau * ma / 0xffff
- }
- pr += float64(pru) * w
- pg += float64(pgu) * w
- pb += float64(pbu) * w
- pa += float64(pau) * w
- }
- }
- }
- }
-
- if pr > pa {
- pr = pa
- }
- if pg > pa {
- pg = pa
- }
- if pb > pa {
- pb = pa
- }
-
- qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
- pr0 := uint32(fffftou(pr))
- pg0 := uint32(fffftou(pg))
- pb0 := uint32(fffftou(pb))
- pa0 := uint32(fffftou(pa))
- if dstMask != nil {
- _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
- pr0 = pr0 * ma / 0xffff
- pg0 = pg0 * ma / 0xffff
- pb0 = pb0 * ma / 0xffff
- pa0 = pa0 * ma / 0xffff
- }
- pa1 := 0xffff - pa0
- dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr0)
- dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg0)
- dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb0)
- dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa0)
- dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
- }
- }
-}
-
-func (q *Kernel) transform_Image_Image_Src(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
- // When shrinking, broaden the effective kernel support so that we still
- // visit every source pixel.
- xHalfWidth, xKernelArgScale := q.Support, 1.0
- if xscale > 1 {
- xHalfWidth *= xscale
- xKernelArgScale = 1 / xscale
- }
- yHalfWidth, yKernelArgScale := q.Support, 1.0
- if yscale > 1 {
- yHalfWidth *= yscale
- yKernelArgScale = 1 / yscale
- }
-
- xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
- yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
-
- srcMask, smp := opts.SrcMask, opts.SrcMaskP
- dstMask, dmp := opts.DstMask, opts.DstMaskP
- dstColorRGBA64 := &color.RGBA64{}
- dstColor := color.Color(dstColorRGBA64)
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- // TODO: adjust the bias so that we can use int(f) instead
- // of math.Floor(f) and math.Ceil(f).
- sx += float64(bias.X)
- sx -= 0.5
- ix := int(math.Floor(sx - xHalfWidth))
- if ix < sr.Min.X {
- ix = sr.Min.X
- }
- jx := int(math.Ceil(sx + xHalfWidth))
- if jx > sr.Max.X {
- jx = sr.Max.X
- }
-
- totalXWeight := 0.0
- for kx := ix; kx < jx; kx++ {
- xWeight := 0.0
- if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
- xWeight = q.At(t)
- }
- xWeights[kx-ix] = xWeight
- totalXWeight += xWeight
- }
- for x := range xWeights[:jx-ix] {
- xWeights[x] /= totalXWeight
- }
-
- sy += float64(bias.Y)
- sy -= 0.5
- iy := int(math.Floor(sy - yHalfWidth))
- if iy < sr.Min.Y {
- iy = sr.Min.Y
- }
- jy := int(math.Ceil(sy + yHalfWidth))
- if jy > sr.Max.Y {
- jy = sr.Max.Y
- }
-
- totalYWeight := 0.0
- for ky := iy; ky < jy; ky++ {
- yWeight := 0.0
- if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
- yWeight = q.At(t)
- }
- yWeights[ky-iy] = yWeight
- totalYWeight += yWeight
- }
- for y := range yWeights[:jy-iy] {
- yWeights[y] /= totalYWeight
- }
-
- var pr, pg, pb, pa float64
- for ky := iy; ky < jy; ky++ {
- if yWeight := yWeights[ky-iy]; yWeight != 0 {
- for kx := ix; kx < jx; kx++ {
- if w := xWeights[kx-ix] * yWeight; w != 0 {
- pru, pgu, pbu, pau := src.At(kx, ky).RGBA()
- if srcMask != nil {
- _, _, _, ma := srcMask.At(smp.X+kx, smp.Y+ky).RGBA()
- pru = pru * ma / 0xffff
- pgu = pgu * ma / 0xffff
- pbu = pbu * ma / 0xffff
- pau = pau * ma / 0xffff
- }
- pr += float64(pru) * w
- pg += float64(pgu) * w
- pb += float64(pbu) * w
- pa += float64(pau) * w
- }
- }
- }
- }
-
- if pr > pa {
- pr = pa
- }
- if pg > pa {
- pg = pa
- }
- if pb > pa {
- pb = pa
- }
-
- if dstMask != nil {
- qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
- _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
- pr := uint32(fffftou(pr)) * ma / 0xffff
- pg := uint32(fffftou(pg)) * ma / 0xffff
- pb := uint32(fffftou(pb)) * ma / 0xffff
- pa := uint32(fffftou(pa)) * ma / 0xffff
- pa1 := 0xffff - ma
- dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
- dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
- dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
- dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
- dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
- } else {
- dstColorRGBA64.R = fffftou(pr)
- dstColorRGBA64.G = fffftou(pg)
- dstColorRGBA64.B = fffftou(pb)
- dstColorRGBA64.A = fffftou(pa)
- dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
- }
- }
- }
-}
diff --git a/vendor/golang.org/x/image/draw/scale.go b/vendor/golang.org/x/image/draw/scale.go
deleted file mode 100644
index 98ab404..0000000
--- a/vendor/golang.org/x/image/draw/scale.go
+++ /dev/null
@@ -1,527 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:generate go run gen.go
-
-package draw
-
-import (
- "image"
- "image/color"
- "math"
- "sync"
-
- "golang.org/x/image/math/f64"
-)
-
-// Copy copies the part of the source image defined by src and sr and writes
-// the result of a Porter-Duff composition to the part of the destination image
-// defined by dst and the translation of sr so that sr.Min translates to dp.
-func Copy(dst Image, dp image.Point, src image.Image, sr image.Rectangle, op Op, opts *Options) {
- var o Options
- if opts != nil {
- o = *opts
- }
- dr := sr.Add(dp.Sub(sr.Min))
- if o.DstMask == nil {
- DrawMask(dst, dr, src, sr.Min, o.SrcMask, o.SrcMaskP.Add(sr.Min), op)
- } else {
- NearestNeighbor.Scale(dst, dr, src, sr, op, opts)
- }
-}
-
-// Scaler scales the part of the source image defined by src and sr and writes
-// the result of a Porter-Duff composition to the part of the destination image
-// defined by dst and dr.
-//
-// A Scaler is safe to use concurrently.
-type Scaler interface {
- Scale(dst Image, dr image.Rectangle, src image.Image, sr image.Rectangle, op Op, opts *Options)
-}
-
-// Transformer transforms the part of the source image defined by src and sr
-// and writes the result of a Porter-Duff composition to the part of the
-// destination image defined by dst and the affine transform m applied to sr.
-//
-// For example, if m is the matrix
-//
-// m00 m01 m02
-// m10 m11 m12
-//
-// then the src-space point (sx, sy) maps to the dst-space point
-// (m00*sx + m01*sy + m02, m10*sx + m11*sy + m12).
-//
-// A Transformer is safe to use concurrently.
-type Transformer interface {
- Transform(dst Image, m f64.Aff3, src image.Image, sr image.Rectangle, op Op, opts *Options)
-}
-
-// Options are optional parameters to Copy, Scale and Transform.
-//
-// A nil *Options means to use the default (zero) values of each field.
-type Options struct {
- // Masks limit what parts of the dst image are drawn to and what parts of
- // the src image are drawn from.
- //
- // A dst or src mask image having a zero alpha (transparent) pixel value in
- // the respective coordinate space means that that dst pixel is entirely
- // unaffected or that src pixel is considered transparent black. A full
- // alpha (opaque) value means that the dst pixel is maximally affected or
- // the src pixel contributes maximally. The default values, nil, are
- // equivalent to fully opaque, infinitely large mask images.
- //
- // The DstMask is otherwise known as a clip mask, and its pixels map 1:1 to
- // the dst image's pixels. DstMaskP in DstMask space corresponds to
- // image.Point{X:0, Y:0} in dst space. For example, when limiting
- // repainting to a 'dirty rectangle', use that image.Rectangle and a zero
- // image.Point as the DstMask and DstMaskP.
- //
- // The SrcMask's pixels map 1:1 to the src image's pixels. SrcMaskP in
- // SrcMask space corresponds to image.Point{X:0, Y:0} in src space. For
- // example, when drawing font glyphs in a uniform color, use an
- // *image.Uniform as the src, and use the glyph atlas image and the
- // per-glyph offset as SrcMask and SrcMaskP:
- // Copy(dst, dp, image.NewUniform(color), image.Rect(0, 0, glyphWidth, glyphHeight), &Options{
- // SrcMask: glyphAtlas,
- // SrcMaskP: glyphOffset,
- // })
- DstMask image.Image
- DstMaskP image.Point
- SrcMask image.Image
- SrcMaskP image.Point
-
- // TODO: a smooth vs sharp edges option, for arbitrary rotations?
-}
-
-// Interpolator is an interpolation algorithm, when dst and src pixels don't
-// have a 1:1 correspondence.
-//
-// Of the interpolators provided by this package:
-// - NearestNeighbor is fast but usually looks worst.
-// - CatmullRom is slow but usually looks best.
-// - ApproxBiLinear has reasonable speed and quality.
-//
-// The time taken depends on the size of dr. For kernel interpolators, the
-// speed also depends on the size of sr, and so are often slower than
-// non-kernel interpolators, especially when scaling down.
-type Interpolator interface {
- Scaler
- Transformer
-}
-
-// Kernel is an interpolator that blends source pixels weighted by a symmetric
-// kernel function.
-type Kernel struct {
- // Support is the kernel support and must be >= 0. At(t) is assumed to be
- // zero when t >= Support.
- Support float64
- // At is the kernel function. It will only be called with t in the
- // range [0, Support).
- At func(t float64) float64
-}
-
-// Scale implements the Scaler interface.
-func (q *Kernel) Scale(dst Image, dr image.Rectangle, src image.Image, sr image.Rectangle, op Op, opts *Options) {
- q.newScaler(dr.Dx(), dr.Dy(), sr.Dx(), sr.Dy(), false).Scale(dst, dr, src, sr, op, opts)
-}
-
-// NewScaler returns a Scaler that is optimized for scaling multiple times with
-// the same fixed destination and source width and height.
-func (q *Kernel) NewScaler(dw, dh, sw, sh int) Scaler {
- return q.newScaler(dw, dh, sw, sh, true)
-}
-
-func (q *Kernel) newScaler(dw, dh, sw, sh int, usePool bool) Scaler {
- z := &kernelScaler{
- kernel: q,
- dw: int32(dw),
- dh: int32(dh),
- sw: int32(sw),
- sh: int32(sh),
- horizontal: newDistrib(q, int32(dw), int32(sw)),
- vertical: newDistrib(q, int32(dh), int32(sh)),
- }
- if usePool {
- z.pool.New = func() interface{} {
- tmp := z.makeTmpBuf()
- return &tmp
- }
- }
- return z
-}
-
-var (
- // NearestNeighbor is the nearest neighbor interpolator. It is very fast,
- // but usually gives very low quality results. When scaling up, the result
- // will look 'blocky'.
- NearestNeighbor = Interpolator(nnInterpolator{})
-
- // ApproxBiLinear is a mixture of the nearest neighbor and bi-linear
- // interpolators. It is fast, but usually gives medium quality results.
- //
- // It implements bi-linear interpolation when upscaling and a bi-linear
- // blend of the 4 nearest neighbor pixels when downscaling. This yields
- // nicer quality than nearest neighbor interpolation when upscaling, but
- // the time taken is independent of the number of source pixels, unlike the
- // bi-linear interpolator. When downscaling a large image, the performance
- // difference can be significant.
- ApproxBiLinear = Interpolator(ablInterpolator{})
-
- // BiLinear is the tent kernel. It is slow, but usually gives high quality
- // results.
- BiLinear = &Kernel{1, func(t float64) float64 {
- return 1 - t
- }}
-
- // CatmullRom is the Catmull-Rom kernel. It is very slow, but usually gives
- // very high quality results.
- //
- // It is an instance of the more general cubic BC-spline kernel with parameters
- // B=0 and C=0.5. See Mitchell and Netravali, "Reconstruction Filters in
- // Computer Graphics", Computer Graphics, Vol. 22, No. 4, pp. 221-228.
- CatmullRom = &Kernel{2, func(t float64) float64 {
- if t < 1 {
- return (1.5*t-2.5)*t*t + 1
- }
- return ((-0.5*t+2.5)*t-4)*t + 2
- }}
-
- // TODO: a Kaiser-Bessel kernel?
-)
-
-type nnInterpolator struct{}
-
-type ablInterpolator struct{}
-
-type kernelScaler struct {
- kernel *Kernel
- dw, dh, sw, sh int32
- horizontal, vertical distrib
- pool sync.Pool
-}
-
-func (z *kernelScaler) makeTmpBuf() [][4]float64 {
- return make([][4]float64, z.dw*z.sh)
-}
-
-// source is a range of contribs, their inverse total weight, and that ITW
-// divided by 0xffff.
-type source struct {
- i, j int32
- invTotalWeight float64
- invTotalWeightFFFF float64
-}
-
-// contrib is the weight of a column or row.
-type contrib struct {
- coord int32
- weight float64
-}
-
-// distrib measures how source pixels are distributed over destination pixels.
-type distrib struct {
- // sources are what contribs each column or row in the source image owns,
- // and the total weight of those contribs.
- sources []source
- // contribs are the contributions indexed by sources[s].i and sources[s].j.
- contribs []contrib
-}
-
-// newDistrib returns a distrib that distributes sw source columns (or rows)
-// over dw destination columns (or rows).
-func newDistrib(q *Kernel, dw, sw int32) distrib {
- scale := float64(sw) / float64(dw)
- halfWidth, kernelArgScale := q.Support, 1.0
- // When shrinking, broaden the effective kernel support so that we still
- // visit every source pixel.
- if scale > 1 {
- halfWidth *= scale
- kernelArgScale = 1 / scale
- }
-
- // Make the sources slice, one source for each column or row, and temporarily
- // appropriate its elements' fields so that invTotalWeight is the scaled
- // coordinate of the source column or row, and i and j are the lower and
- // upper bounds of the range of destination columns or rows affected by the
- // source column or row.
- n, sources := int32(0), make([]source, dw)
- for x := range sources {
- center := (float64(x)+0.5)*scale - 0.5
- i := int32(math.Floor(center - halfWidth))
- if i < 0 {
- i = 0
- }
- j := int32(math.Ceil(center + halfWidth))
- if j > sw {
- j = sw
- if j < i {
- j = i
- }
- }
- sources[x] = source{i: i, j: j, invTotalWeight: center}
- n += j - i
- }
-
- contribs := make([]contrib, 0, n)
- for k, b := range sources {
- totalWeight := 0.0
- l := int32(len(contribs))
- for coord := b.i; coord < b.j; coord++ {
- t := abs((b.invTotalWeight - float64(coord)) * kernelArgScale)
- if t >= q.Support {
- continue
- }
- weight := q.At(t)
- if weight == 0 {
- continue
- }
- totalWeight += weight
- contribs = append(contribs, contrib{coord, weight})
- }
- totalWeight = 1 / totalWeight
- sources[k] = source{
- i: l,
- j: int32(len(contribs)),
- invTotalWeight: totalWeight,
- invTotalWeightFFFF: totalWeight / 0xffff,
- }
- }
-
- return distrib{sources, contribs}
-}
-
-// abs is like math.Abs, but it doesn't care about negative zero, infinities or
-// NaNs.
-func abs(f float64) float64 {
- if f < 0 {
- f = -f
- }
- return f
-}
-
-// ftou converts the range [0.0, 1.0] to [0, 0xffff].
-func ftou(f float64) uint16 {
- i := int32(0xffff*f + 0.5)
- if i > 0xffff {
- return 0xffff
- }
- if i > 0 {
- return uint16(i)
- }
- return 0
-}
-
-// fffftou converts the range [0.0, 65535.0] to [0, 0xffff].
-func fffftou(f float64) uint16 {
- i := int32(f + 0.5)
- if i > 0xffff {
- return 0xffff
- }
- if i > 0 {
- return uint16(i)
- }
- return 0
-}
-
-// invert returns the inverse of m.
-//
-// TODO: move this into the f64 package, once we work out the convention for
-// matrix methods in that package: do they modify the receiver, take a dst
-// pointer argument, or return a new value?
-func invert(m *f64.Aff3) f64.Aff3 {
- m00 := +m[3*1+1]
- m01 := -m[3*0+1]
- m02 := +m[3*1+2]*m[3*0+1] - m[3*1+1]*m[3*0+2]
- m10 := -m[3*1+0]
- m11 := +m[3*0+0]
- m12 := +m[3*1+0]*m[3*0+2] - m[3*1+2]*m[3*0+0]
-
- det := m00*m11 - m10*m01
-
- return f64.Aff3{
- m00 / det,
- m01 / det,
- m02 / det,
- m10 / det,
- m11 / det,
- m12 / det,
- }
-}
-
-func matMul(p, q *f64.Aff3) f64.Aff3 {
- return f64.Aff3{
- p[3*0+0]*q[3*0+0] + p[3*0+1]*q[3*1+0],
- p[3*0+0]*q[3*0+1] + p[3*0+1]*q[3*1+1],
- p[3*0+0]*q[3*0+2] + p[3*0+1]*q[3*1+2] + p[3*0+2],
- p[3*1+0]*q[3*0+0] + p[3*1+1]*q[3*1+0],
- p[3*1+0]*q[3*0+1] + p[3*1+1]*q[3*1+1],
- p[3*1+0]*q[3*0+2] + p[3*1+1]*q[3*1+2] + p[3*1+2],
- }
-}
-
-// transformRect returns a rectangle dr that contains sr transformed by s2d.
-func transformRect(s2d *f64.Aff3, sr *image.Rectangle) (dr image.Rectangle) {
- ps := [...]image.Point{
- {sr.Min.X, sr.Min.Y},
- {sr.Max.X, sr.Min.Y},
- {sr.Min.X, sr.Max.Y},
- {sr.Max.X, sr.Max.Y},
- }
- for i, p := range ps {
- sxf := float64(p.X)
- syf := float64(p.Y)
- dx := int(math.Floor(s2d[0]*sxf + s2d[1]*syf + s2d[2]))
- dy := int(math.Floor(s2d[3]*sxf + s2d[4]*syf + s2d[5]))
-
- // The +1 adjustments below are because an image.Rectangle is inclusive
- // on the low end but exclusive on the high end.
-
- if i == 0 {
- dr = image.Rectangle{
- Min: image.Point{dx + 0, dy + 0},
- Max: image.Point{dx + 1, dy + 1},
- }
- continue
- }
-
- if dr.Min.X > dx {
- dr.Min.X = dx
- }
- dx++
- if dr.Max.X < dx {
- dr.Max.X = dx
- }
-
- if dr.Min.Y > dy {
- dr.Min.Y = dy
- }
- dy++
- if dr.Max.Y < dy {
- dr.Max.Y = dy
- }
- }
- return dr
-}
-
-func clipAffectedDestRect(adr image.Rectangle, dstMask image.Image, dstMaskP image.Point) (image.Rectangle, image.Image) {
- if dstMask == nil {
- return adr, nil
- }
- // TODO: enable this fast path once Go 1.5 is released, where an
- // image.Rectangle implements image.Image.
- // if r, ok := dstMask.(image.Rectangle); ok {
- // return adr.Intersect(r.Sub(dstMaskP)), nil
- // }
- // TODO: clip to dstMask.Bounds() if the color model implies that out-of-bounds means 0 alpha?
- return adr, dstMask
-}
-
-func transform_Uniform(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.Uniform, sr image.Rectangle, bias image.Point, op Op) {
- switch op {
- case Over:
- switch dst := dst.(type) {
- case *image.RGBA:
- pr, pg, pb, pa := src.C.RGBA()
- pa1 := (0xffff - pa) * 0x101
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := dst.PixOffset(dr.Min.X+adr.Min.X, dr.Min.Y+int(dy))
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
- sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
- if !(image.Point{sx0, sy0}).In(sr) {
- continue
- }
- dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
- dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
- dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
- dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
- }
- }
-
- default:
- pr, pg, pb, pa := src.C.RGBA()
- pa1 := 0xffff - pa
- dstColorRGBA64 := &color.RGBA64{}
- dstColor := color.Color(dstColorRGBA64)
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
- sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
- if !(image.Point{sx0, sy0}).In(sr) {
- continue
- }
- qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
- dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
- dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
- dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
- dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
- dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
- }
- }
- }
-
- case Src:
- switch dst := dst.(type) {
- case *image.RGBA:
- pr, pg, pb, pa := src.C.RGBA()
- pr8 := uint8(pr >> 8)
- pg8 := uint8(pg >> 8)
- pb8 := uint8(pb >> 8)
- pa8 := uint8(pa >> 8)
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := dst.PixOffset(dr.Min.X+adr.Min.X, dr.Min.Y+int(dy))
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
- sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
- if !(image.Point{sx0, sy0}).In(sr) {
- continue
- }
- dst.Pix[d+0] = pr8
- dst.Pix[d+1] = pg8
- dst.Pix[d+2] = pb8
- dst.Pix[d+3] = pa8
- }
- }
-
- default:
- pr, pg, pb, pa := src.C.RGBA()
- dstColorRGBA64 := &color.RGBA64{
- uint16(pr),
- uint16(pg),
- uint16(pb),
- uint16(pa),
- }
- dstColor := color.Color(dstColorRGBA64)
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
- sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
- if !(image.Point{sx0, sy0}).In(sr) {
- continue
- }
- dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
- }
- }
- }
- }
-}
-
-func opaque(m image.Image) bool {
- o, ok := m.(interface {
- Opaque() bool
- })
- return ok && o.Opaque()
-}
diff --git a/vendor/golang.org/x/image/math/f64/f64.go b/vendor/golang.org/x/image/math/f64/f64.go
deleted file mode 100644
index a1f7fc0..0000000
--- a/vendor/golang.org/x/image/math/f64/f64.go
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package f64 implements float64 vector and matrix types.
-package f64 // import "golang.org/x/image/math/f64"
-
-// Vec2 is a 2-element vector.
-type Vec2 [2]float64
-
-// Vec3 is a 3-element vector.
-type Vec3 [3]float64
-
-// Vec4 is a 4-element vector.
-type Vec4 [4]float64
-
-// Mat3 is a 3x3 matrix in row major order.
-//
-// m[3*r + c] is the element in the r'th row and c'th column.
-type Mat3 [9]float64
-
-// Mat4 is a 4x4 matrix in row major order.
-//
-// m[4*r + c] is the element in the r'th row and c'th column.
-type Mat4 [16]float64
-
-// Aff3 is a 3x3 affine transformation matrix in row major order, where the
-// bottom row is implicitly [0 0 1].
-//
-// m[3*r + c] is the element in the r'th row and c'th column.
-type Aff3 [6]float64
-
-// Aff4 is a 4x4 affine transformation matrix in row major order, where the
-// bottom row is implicitly [0 0 0 1].
-//
-// m[4*r + c] is the element in the r'th row and c'th column.
-type Aff4 [12]float64
diff --git a/vendor/golang.org/x/image/riff/riff.go b/vendor/golang.org/x/image/riff/riff.go
deleted file mode 100644
index 38dc0e5..0000000
--- a/vendor/golang.org/x/image/riff/riff.go
+++ /dev/null
@@ -1,193 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package riff implements the Resource Interchange File Format, used by media
-// formats such as AVI, WAVE and WEBP.
-//
-// A RIFF stream contains a sequence of chunks. Each chunk consists of an 8-byte
-// header (containing a 4-byte chunk type and a 4-byte chunk length), the chunk
-// data (presented as an io.Reader), and some padding bytes.
-//
-// A detailed description of the format is at
-// http://www.tactilemedia.com/info/MCI_Control_Info.html
-package riff // import "golang.org/x/image/riff"
-
-import (
- "errors"
- "io"
- "io/ioutil"
- "math"
-)
-
-var (
- errMissingPaddingByte = errors.New("riff: missing padding byte")
- errMissingRIFFChunkHeader = errors.New("riff: missing RIFF chunk header")
- errListSubchunkTooLong = errors.New("riff: list subchunk too long")
- errShortChunkData = errors.New("riff: short chunk data")
- errShortChunkHeader = errors.New("riff: short chunk header")
- errStaleReader = errors.New("riff: stale reader")
-)
-
-// u32 decodes the first four bytes of b as a little-endian integer.
-func u32(b []byte) uint32 {
- return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
-}
-
-const chunkHeaderSize = 8
-
-// FourCC is a four character code.
-type FourCC [4]byte
-
-// LIST is the "LIST" FourCC.
-var LIST = FourCC{'L', 'I', 'S', 'T'}
-
-// NewReader returns the RIFF stream's form type, such as "AVI " or "WAVE", and
-// its chunks as a *Reader.
-func NewReader(r io.Reader) (formType FourCC, data *Reader, err error) {
- var buf [chunkHeaderSize]byte
- if _, err := io.ReadFull(r, buf[:]); err != nil {
- if err == io.EOF || err == io.ErrUnexpectedEOF {
- err = errMissingRIFFChunkHeader
- }
- return FourCC{}, nil, err
- }
- if buf[0] != 'R' || buf[1] != 'I' || buf[2] != 'F' || buf[3] != 'F' {
- return FourCC{}, nil, errMissingRIFFChunkHeader
- }
- return NewListReader(u32(buf[4:]), r)
-}
-
-// NewListReader returns a LIST chunk's list type, such as "movi" or "wavl",
-// and its chunks as a *Reader.
-func NewListReader(chunkLen uint32, chunkData io.Reader) (listType FourCC, data *Reader, err error) {
- if chunkLen < 4 {
- return FourCC{}, nil, errShortChunkData
- }
- z := &Reader{r: chunkData}
- if _, err := io.ReadFull(chunkData, z.buf[:4]); err != nil {
- if err == io.EOF || err == io.ErrUnexpectedEOF {
- err = errShortChunkData
- }
- return FourCC{}, nil, err
- }
- z.totalLen = chunkLen - 4
- return FourCC{z.buf[0], z.buf[1], z.buf[2], z.buf[3]}, z, nil
-}
-
-// Reader reads chunks from an underlying io.Reader.
-type Reader struct {
- r io.Reader
- err error
-
- totalLen uint32
- chunkLen uint32
-
- chunkReader *chunkReader
- buf [chunkHeaderSize]byte
- padded bool
-}
-
-// Next returns the next chunk's ID, length and data. It returns io.EOF if there
-// are no more chunks. The io.Reader returned becomes stale after the next Next
-// call, and should no longer be used.
-//
-// It is valid to call Next even if all of the previous chunk's data has not
-// been read.
-func (z *Reader) Next() (chunkID FourCC, chunkLen uint32, chunkData io.Reader, err error) {
- if z.err != nil {
- return FourCC{}, 0, nil, z.err
- }
-
- // Drain the rest of the previous chunk.
- if z.chunkLen != 0 {
- want := z.chunkLen
- var got int64
- got, z.err = io.Copy(ioutil.Discard, z.chunkReader)
- if z.err == nil && uint32(got) != want {
- z.err = errShortChunkData
- }
- if z.err != nil {
- return FourCC{}, 0, nil, z.err
- }
- }
- z.chunkReader = nil
- if z.padded {
- if z.totalLen == 0 {
- z.err = errListSubchunkTooLong
- return FourCC{}, 0, nil, z.err
- }
- z.totalLen--
- _, z.err = io.ReadFull(z.r, z.buf[:1])
- if z.err != nil {
- if z.err == io.EOF {
- z.err = errMissingPaddingByte
- }
- return FourCC{}, 0, nil, z.err
- }
- }
-
- // We are done if we have no more data.
- if z.totalLen == 0 {
- z.err = io.EOF
- return FourCC{}, 0, nil, z.err
- }
-
- // Read the next chunk header.
- if z.totalLen < chunkHeaderSize {
- z.err = errShortChunkHeader
- return FourCC{}, 0, nil, z.err
- }
- z.totalLen -= chunkHeaderSize
- if _, z.err = io.ReadFull(z.r, z.buf[:chunkHeaderSize]); z.err != nil {
- if z.err == io.EOF || z.err == io.ErrUnexpectedEOF {
- z.err = errShortChunkHeader
- }
- return FourCC{}, 0, nil, z.err
- }
- chunkID = FourCC{z.buf[0], z.buf[1], z.buf[2], z.buf[3]}
- z.chunkLen = u32(z.buf[4:])
- if z.chunkLen > z.totalLen {
- z.err = errListSubchunkTooLong
- return FourCC{}, 0, nil, z.err
- }
- z.padded = z.chunkLen&1 == 1
- z.chunkReader = &chunkReader{z}
- return chunkID, z.chunkLen, z.chunkReader, nil
-}
-
-type chunkReader struct {
- z *Reader
-}
-
-func (c *chunkReader) Read(p []byte) (int, error) {
- if c != c.z.chunkReader {
- return 0, errStaleReader
- }
- z := c.z
- if z.err != nil {
- if z.err == io.EOF {
- return 0, errStaleReader
- }
- return 0, z.err
- }
-
- n := int(z.chunkLen)
- if n == 0 {
- return 0, io.EOF
- }
- if n < 0 {
- // Converting uint32 to int overflowed.
- n = math.MaxInt32
- }
- if n > len(p) {
- n = len(p)
- }
- n, err := z.r.Read(p[:n])
- z.totalLen -= uint32(n)
- z.chunkLen -= uint32(n)
- if err != io.EOF {
- z.err = err
- }
- return n, err
-}
diff --git a/vendor/golang.org/x/image/vp8/decode.go b/vendor/golang.org/x/image/vp8/decode.go
deleted file mode 100644
index 1bb5028..0000000
--- a/vendor/golang.org/x/image/vp8/decode.go
+++ /dev/null
@@ -1,403 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package vp8 implements a decoder for the VP8 lossy image format.
-//
-// The VP8 specification is RFC 6386.
-package vp8 // import "golang.org/x/image/vp8"
-
-// This file implements the top-level decoding algorithm.
-
-import (
- "errors"
- "image"
- "io"
-)
-
-// limitReader wraps an io.Reader to read at most n bytes from it.
-type limitReader struct {
- r io.Reader
- n int
-}
-
-// ReadFull reads exactly len(p) bytes into p.
-func (r *limitReader) ReadFull(p []byte) error {
- if len(p) > r.n {
- return io.ErrUnexpectedEOF
- }
- n, err := io.ReadFull(r.r, p)
- r.n -= n
- return err
-}
-
-// FrameHeader is a frame header, as specified in section 9.1.
-type FrameHeader struct {
- KeyFrame bool
- VersionNumber uint8
- ShowFrame bool
- FirstPartitionLen uint32
- Width int
- Height int
- XScale uint8
- YScale uint8
-}
-
-const (
- nSegment = 4
- nSegmentProb = 3
-)
-
-// segmentHeader holds segment-related header information.
-type segmentHeader struct {
- useSegment bool
- updateMap bool
- relativeDelta bool
- quantizer [nSegment]int8
- filterStrength [nSegment]int8
- prob [nSegmentProb]uint8
-}
-
-const (
- nRefLFDelta = 4
- nModeLFDelta = 4
-)
-
-// filterHeader holds filter-related header information.
-type filterHeader struct {
- simple bool
- level int8
- sharpness uint8
- useLFDelta bool
- refLFDelta [nRefLFDelta]int8
- modeLFDelta [nModeLFDelta]int8
- perSegmentLevel [nSegment]int8
-}
-
-// mb is the per-macroblock decode state. A decoder maintains mbw+1 of these
-// as it is decoding macroblocks left-to-right and top-to-bottom: mbw for the
-// macroblocks in the row above, and one for the macroblock to the left.
-type mb struct {
- // pred is the predictor mode for the 4 bottom or right 4x4 luma regions.
- pred [4]uint8
- // nzMask is a mask of 8 bits: 4 for the bottom or right 4x4 luma regions,
- // and 2 + 2 for the bottom or right 4x4 chroma regions. A 1 bit indicates
- // that that region has non-zero coefficients.
- nzMask uint8
- // nzY16 is a 0/1 value that is 1 if the macroblock used Y16 prediction and
- // had non-zero coefficients.
- nzY16 uint8
-}
-
-// Decoder decodes VP8 bitstreams into frames. Decoding one frame consists of
-// calling Init, DecodeFrameHeader and then DecodeFrame in that order.
-// A Decoder can be re-used to decode multiple frames.
-type Decoder struct {
- // r is the input bitsream.
- r limitReader
- // scratch is a scratch buffer.
- scratch [8]byte
- // img is the YCbCr image to decode into.
- img *image.YCbCr
- // mbw and mbh are the number of 16x16 macroblocks wide and high the image is.
- mbw, mbh int
- // frameHeader is the frame header. When decoding multiple frames,
- // frames that aren't key frames will inherit the Width, Height,
- // XScale and YScale of the most recent key frame.
- frameHeader FrameHeader
- // Other headers.
- segmentHeader segmentHeader
- filterHeader filterHeader
- // The image data is divided into a number of independent partitions.
- // There is 1 "first partition" and between 1 and 8 "other partitions"
- // for coefficient data.
- fp partition
- op [8]partition
- nOP int
- // Quantization factors.
- quant [nSegment]quant
- // DCT/WHT coefficient decoding probabilities.
- tokenProb [nPlane][nBand][nContext][nProb]uint8
- useSkipProb bool
- skipProb uint8
- // Loop filter parameters.
- filterParams [nSegment][2]filterParam
- perMBFilterParams []filterParam
-
- // The eight fields below relate to the current macroblock being decoded.
- //
- // Segment-based adjustments.
- segment int
- // Per-macroblock state for the macroblock immediately left of and those
- // macroblocks immediately above the current macroblock.
- leftMB mb
- upMB []mb
- // Bitmasks for which 4x4 regions of coeff contain non-zero coefficients.
- nzDCMask, nzACMask uint32
- // Predictor modes.
- usePredY16 bool // The libwebp C code calls this !is_i4x4_.
- predY16 uint8
- predC8 uint8
- predY4 [4][4]uint8
-
- // The two fields below form a workspace for reconstructing a macroblock.
- // Their specific sizes are documented in reconstruct.go.
- coeff [1*16*16 + 2*8*8 + 1*4*4]int16
- ybr [1 + 16 + 1 + 8][32]uint8
-}
-
-// NewDecoder returns a new Decoder.
-func NewDecoder() *Decoder {
- return &Decoder{}
-}
-
-// Init initializes the decoder to read at most n bytes from r.
-func (d *Decoder) Init(r io.Reader, n int) {
- d.r = limitReader{r, n}
-}
-
-// DecodeFrameHeader decodes the frame header.
-func (d *Decoder) DecodeFrameHeader() (fh FrameHeader, err error) {
- // All frame headers are at least 3 bytes long.
- b := d.scratch[:3]
- if err = d.r.ReadFull(b); err != nil {
- return
- }
- d.frameHeader.KeyFrame = (b[0] & 1) == 0
- d.frameHeader.VersionNumber = (b[0] >> 1) & 7
- d.frameHeader.ShowFrame = (b[0]>>4)&1 == 1
- d.frameHeader.FirstPartitionLen = uint32(b[0])>>5 | uint32(b[1])<<3 | uint32(b[2])<<11
- if !d.frameHeader.KeyFrame {
- return d.frameHeader, nil
- }
- // Frame headers for key frames are an additional 7 bytes long.
- b = d.scratch[:7]
- if err = d.r.ReadFull(b); err != nil {
- return
- }
- // Check the magic sync code.
- if b[0] != 0x9d || b[1] != 0x01 || b[2] != 0x2a {
- err = errors.New("vp8: invalid format")
- return
- }
- d.frameHeader.Width = int(b[4]&0x3f)<<8 | int(b[3])
- d.frameHeader.Height = int(b[6]&0x3f)<<8 | int(b[5])
- d.frameHeader.XScale = b[4] >> 6
- d.frameHeader.YScale = b[6] >> 6
- d.mbw = (d.frameHeader.Width + 0x0f) >> 4
- d.mbh = (d.frameHeader.Height + 0x0f) >> 4
- d.segmentHeader = segmentHeader{
- prob: [3]uint8{0xff, 0xff, 0xff},
- }
- d.tokenProb = defaultTokenProb
- d.segment = 0
- return d.frameHeader, nil
-}
-
-// ensureImg ensures that d.img is large enough to hold the decoded frame.
-func (d *Decoder) ensureImg() {
- if d.img != nil {
- p0, p1 := d.img.Rect.Min, d.img.Rect.Max
- if p0.X == 0 && p0.Y == 0 && p1.X >= 16*d.mbw && p1.Y >= 16*d.mbh {
- return
- }
- }
- m := image.NewYCbCr(image.Rect(0, 0, 16*d.mbw, 16*d.mbh), image.YCbCrSubsampleRatio420)
- d.img = m.SubImage(image.Rect(0, 0, d.frameHeader.Width, d.frameHeader.Height)).(*image.YCbCr)
- d.perMBFilterParams = make([]filterParam, d.mbw*d.mbh)
- d.upMB = make([]mb, d.mbw)
-}
-
-// parseSegmentHeader parses the segment header, as specified in section 9.3.
-func (d *Decoder) parseSegmentHeader() {
- d.segmentHeader.useSegment = d.fp.readBit(uniformProb)
- if !d.segmentHeader.useSegment {
- d.segmentHeader.updateMap = false
- return
- }
- d.segmentHeader.updateMap = d.fp.readBit(uniformProb)
- if d.fp.readBit(uniformProb) {
- d.segmentHeader.relativeDelta = !d.fp.readBit(uniformProb)
- for i := range d.segmentHeader.quantizer {
- d.segmentHeader.quantizer[i] = int8(d.fp.readOptionalInt(uniformProb, 7))
- }
- for i := range d.segmentHeader.filterStrength {
- d.segmentHeader.filterStrength[i] = int8(d.fp.readOptionalInt(uniformProb, 6))
- }
- }
- if !d.segmentHeader.updateMap {
- return
- }
- for i := range d.segmentHeader.prob {
- if d.fp.readBit(uniformProb) {
- d.segmentHeader.prob[i] = uint8(d.fp.readUint(uniformProb, 8))
- } else {
- d.segmentHeader.prob[i] = 0xff
- }
- }
-}
-
-// parseFilterHeader parses the filter header, as specified in section 9.4.
-func (d *Decoder) parseFilterHeader() {
- d.filterHeader.simple = d.fp.readBit(uniformProb)
- d.filterHeader.level = int8(d.fp.readUint(uniformProb, 6))
- d.filterHeader.sharpness = uint8(d.fp.readUint(uniformProb, 3))
- d.filterHeader.useLFDelta = d.fp.readBit(uniformProb)
- if d.filterHeader.useLFDelta && d.fp.readBit(uniformProb) {
- for i := range d.filterHeader.refLFDelta {
- d.filterHeader.refLFDelta[i] = int8(d.fp.readOptionalInt(uniformProb, 6))
- }
- for i := range d.filterHeader.modeLFDelta {
- d.filterHeader.modeLFDelta[i] = int8(d.fp.readOptionalInt(uniformProb, 6))
- }
- }
- if d.filterHeader.level == 0 {
- return
- }
- if d.segmentHeader.useSegment {
- for i := range d.filterHeader.perSegmentLevel {
- strength := d.segmentHeader.filterStrength[i]
- if d.segmentHeader.relativeDelta {
- strength += d.filterHeader.level
- }
- d.filterHeader.perSegmentLevel[i] = strength
- }
- } else {
- d.filterHeader.perSegmentLevel[0] = d.filterHeader.level
- }
- d.computeFilterParams()
-}
-
-// parseOtherPartitions parses the other partitions, as specified in section 9.5.
-func (d *Decoder) parseOtherPartitions() error {
- const maxNOP = 1 << 3
- var partLens [maxNOP]int
- d.nOP = 1 << d.fp.readUint(uniformProb, 2)
-
- // The final partition length is implied by the the remaining chunk data
- // (d.r.n) and the other d.nOP-1 partition lengths. Those d.nOP-1 partition
- // lengths are stored as 24-bit uints, i.e. up to 16 MiB per partition.
- n := 3 * (d.nOP - 1)
- partLens[d.nOP-1] = d.r.n - n
- if partLens[d.nOP-1] < 0 {
- return io.ErrUnexpectedEOF
- }
- if n > 0 {
- buf := make([]byte, n)
- if err := d.r.ReadFull(buf); err != nil {
- return err
- }
- for i := 0; i < d.nOP-1; i++ {
- pl := int(buf[3*i+0]) | int(buf[3*i+1])<<8 | int(buf[3*i+2])<<16
- if pl > partLens[d.nOP-1] {
- return io.ErrUnexpectedEOF
- }
- partLens[i] = pl
- partLens[d.nOP-1] -= pl
- }
- }
-
- // We check if the final partition length can also fit into a 24-bit uint.
- // Strictly speaking, this isn't part of the spec, but it guards against a
- // malicious WEBP image that is too large to ReadFull the encoded DCT
- // coefficients into memory, whether that's because the actual WEBP file is
- // too large, or whether its RIFF metadata lists too large a chunk.
- if 1<<24 <= partLens[d.nOP-1] {
- return errors.New("vp8: too much data to decode")
- }
-
- buf := make([]byte, d.r.n)
- if err := d.r.ReadFull(buf); err != nil {
- return err
- }
- for i, pl := range partLens {
- if i == d.nOP {
- break
- }
- d.op[i].init(buf[:pl])
- buf = buf[pl:]
- }
- return nil
-}
-
-// parseOtherHeaders parses header information other than the frame header.
-func (d *Decoder) parseOtherHeaders() error {
- // Initialize and parse the first partition.
- firstPartition := make([]byte, d.frameHeader.FirstPartitionLen)
- if err := d.r.ReadFull(firstPartition); err != nil {
- return err
- }
- d.fp.init(firstPartition)
- if d.frameHeader.KeyFrame {
- // Read and ignore the color space and pixel clamp values. They are
- // specified in section 9.2, but are unimplemented.
- d.fp.readBit(uniformProb)
- d.fp.readBit(uniformProb)
- }
- d.parseSegmentHeader()
- d.parseFilterHeader()
- if err := d.parseOtherPartitions(); err != nil {
- return err
- }
- d.parseQuant()
- if !d.frameHeader.KeyFrame {
- // Golden and AltRef frames are specified in section 9.7.
- // TODO(nigeltao): implement. Note that they are only used for video, not still images.
- return errors.New("vp8: Golden / AltRef frames are not implemented")
- }
- // Read and ignore the refreshLastFrameBuffer bit, specified in section 9.8.
- // It applies only to video, and not still images.
- d.fp.readBit(uniformProb)
- d.parseTokenProb()
- d.useSkipProb = d.fp.readBit(uniformProb)
- if d.useSkipProb {
- d.skipProb = uint8(d.fp.readUint(uniformProb, 8))
- }
- if d.fp.unexpectedEOF {
- return io.ErrUnexpectedEOF
- }
- return nil
-}
-
-// DecodeFrame decodes the frame and returns it as an YCbCr image.
-// The image's contents are valid up until the next call to Decoder.Init.
-func (d *Decoder) DecodeFrame() (*image.YCbCr, error) {
- d.ensureImg()
- if err := d.parseOtherHeaders(); err != nil {
- return nil, err
- }
- // Reconstruct the rows.
- for mbx := 0; mbx < d.mbw; mbx++ {
- d.upMB[mbx] = mb{}
- }
- for mby := 0; mby < d.mbh; mby++ {
- d.leftMB = mb{}
- for mbx := 0; mbx < d.mbw; mbx++ {
- skip := d.reconstruct(mbx, mby)
- fs := d.filterParams[d.segment][btou(!d.usePredY16)]
- fs.inner = fs.inner || !skip
- d.perMBFilterParams[d.mbw*mby+mbx] = fs
- }
- }
- if d.fp.unexpectedEOF {
- return nil, io.ErrUnexpectedEOF
- }
- for i := 0; i < d.nOP; i++ {
- if d.op[i].unexpectedEOF {
- return nil, io.ErrUnexpectedEOF
- }
- }
- // Apply the loop filter.
- //
- // Even if we are using per-segment levels, section 15 says that "loop
- // filtering must be skipped entirely if loop_filter_level at either the
- // frame header level or macroblock override level is 0".
- if d.filterHeader.level != 0 {
- if d.filterHeader.simple {
- d.simpleFilter()
- } else {
- d.normalFilter()
- }
- }
- return d.img, nil
-}
diff --git a/vendor/golang.org/x/image/vp8/filter.go b/vendor/golang.org/x/image/vp8/filter.go
deleted file mode 100644
index e34a811..0000000
--- a/vendor/golang.org/x/image/vp8/filter.go
+++ /dev/null
@@ -1,273 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package vp8
-
-// filter2 modifies a 2-pixel wide or 2-pixel high band along an edge.
-func filter2(pix []byte, level, index, iStep, jStep int) {
- for n := 16; n > 0; n, index = n-1, index+iStep {
- p1 := int(pix[index-2*jStep])
- p0 := int(pix[index-1*jStep])
- q0 := int(pix[index+0*jStep])
- q1 := int(pix[index+1*jStep])
- if abs(p0-q0)<<1+abs(p1-q1)>>1 > level {
- continue
- }
- a := 3*(q0-p0) + clamp127(p1-q1)
- a1 := clamp15((a + 4) >> 3)
- a2 := clamp15((a + 3) >> 3)
- pix[index-1*jStep] = clamp255(p0 + a2)
- pix[index+0*jStep] = clamp255(q0 - a1)
- }
-}
-
-// filter246 modifies a 2-, 4- or 6-pixel wide or high band along an edge.
-func filter246(pix []byte, n, level, ilevel, hlevel, index, iStep, jStep int, fourNotSix bool) {
- for ; n > 0; n, index = n-1, index+iStep {
- p3 := int(pix[index-4*jStep])
- p2 := int(pix[index-3*jStep])
- p1 := int(pix[index-2*jStep])
- p0 := int(pix[index-1*jStep])
- q0 := int(pix[index+0*jStep])
- q1 := int(pix[index+1*jStep])
- q2 := int(pix[index+2*jStep])
- q3 := int(pix[index+3*jStep])
- if abs(p0-q0)<<1+abs(p1-q1)>>1 > level {
- continue
- }
- if abs(p3-p2) > ilevel ||
- abs(p2-p1) > ilevel ||
- abs(p1-p0) > ilevel ||
- abs(q1-q0) > ilevel ||
- abs(q2-q1) > ilevel ||
- abs(q3-q2) > ilevel {
- continue
- }
- if abs(p1-p0) > hlevel || abs(q1-q0) > hlevel {
- // Filter 2 pixels.
- a := 3*(q0-p0) + clamp127(p1-q1)
- a1 := clamp15((a + 4) >> 3)
- a2 := clamp15((a + 3) >> 3)
- pix[index-1*jStep] = clamp255(p0 + a2)
- pix[index+0*jStep] = clamp255(q0 - a1)
- } else if fourNotSix {
- // Filter 4 pixels.
- a := 3 * (q0 - p0)
- a1 := clamp15((a + 4) >> 3)
- a2 := clamp15((a + 3) >> 3)
- a3 := (a1 + 1) >> 1
- pix[index-2*jStep] = clamp255(p1 + a3)
- pix[index-1*jStep] = clamp255(p0 + a2)
- pix[index+0*jStep] = clamp255(q0 - a1)
- pix[index+1*jStep] = clamp255(q1 - a3)
- } else {
- // Filter 6 pixels.
- a := clamp127(3*(q0-p0) + clamp127(p1-q1))
- a1 := (27*a + 63) >> 7
- a2 := (18*a + 63) >> 7
- a3 := (9*a + 63) >> 7
- pix[index-3*jStep] = clamp255(p2 + a3)
- pix[index-2*jStep] = clamp255(p1 + a2)
- pix[index-1*jStep] = clamp255(p0 + a1)
- pix[index+0*jStep] = clamp255(q0 - a1)
- pix[index+1*jStep] = clamp255(q1 - a2)
- pix[index+2*jStep] = clamp255(q2 - a3)
- }
- }
-}
-
-// simpleFilter implements the simple filter, as specified in section 15.2.
-func (d *Decoder) simpleFilter() {
- for mby := 0; mby < d.mbh; mby++ {
- for mbx := 0; mbx < d.mbw; mbx++ {
- f := d.perMBFilterParams[d.mbw*mby+mbx]
- if f.level == 0 {
- continue
- }
- l := int(f.level)
- yIndex := (mby*d.img.YStride + mbx) * 16
- if mbx > 0 {
- filter2(d.img.Y, l+4, yIndex, d.img.YStride, 1)
- }
- if f.inner {
- filter2(d.img.Y, l, yIndex+0x4, d.img.YStride, 1)
- filter2(d.img.Y, l, yIndex+0x8, d.img.YStride, 1)
- filter2(d.img.Y, l, yIndex+0xc, d.img.YStride, 1)
- }
- if mby > 0 {
- filter2(d.img.Y, l+4, yIndex, 1, d.img.YStride)
- }
- if f.inner {
- filter2(d.img.Y, l, yIndex+d.img.YStride*0x4, 1, d.img.YStride)
- filter2(d.img.Y, l, yIndex+d.img.YStride*0x8, 1, d.img.YStride)
- filter2(d.img.Y, l, yIndex+d.img.YStride*0xc, 1, d.img.YStride)
- }
- }
- }
-}
-
-// normalFilter implements the normal filter, as specified in section 15.3.
-func (d *Decoder) normalFilter() {
- for mby := 0; mby < d.mbh; mby++ {
- for mbx := 0; mbx < d.mbw; mbx++ {
- f := d.perMBFilterParams[d.mbw*mby+mbx]
- if f.level == 0 {
- continue
- }
- l, il, hl := int(f.level), int(f.ilevel), int(f.hlevel)
- yIndex := (mby*d.img.YStride + mbx) * 16
- cIndex := (mby*d.img.CStride + mbx) * 8
- if mbx > 0 {
- filter246(d.img.Y, 16, l+4, il, hl, yIndex, d.img.YStride, 1, false)
- filter246(d.img.Cb, 8, l+4, il, hl, cIndex, d.img.CStride, 1, false)
- filter246(d.img.Cr, 8, l+4, il, hl, cIndex, d.img.CStride, 1, false)
- }
- if f.inner {
- filter246(d.img.Y, 16, l, il, hl, yIndex+0x4, d.img.YStride, 1, true)
- filter246(d.img.Y, 16, l, il, hl, yIndex+0x8, d.img.YStride, 1, true)
- filter246(d.img.Y, 16, l, il, hl, yIndex+0xc, d.img.YStride, 1, true)
- filter246(d.img.Cb, 8, l, il, hl, cIndex+0x4, d.img.CStride, 1, true)
- filter246(d.img.Cr, 8, l, il, hl, cIndex+0x4, d.img.CStride, 1, true)
- }
- if mby > 0 {
- filter246(d.img.Y, 16, l+4, il, hl, yIndex, 1, d.img.YStride, false)
- filter246(d.img.Cb, 8, l+4, il, hl, cIndex, 1, d.img.CStride, false)
- filter246(d.img.Cr, 8, l+4, il, hl, cIndex, 1, d.img.CStride, false)
- }
- if f.inner {
- filter246(d.img.Y, 16, l, il, hl, yIndex+d.img.YStride*0x4, 1, d.img.YStride, true)
- filter246(d.img.Y, 16, l, il, hl, yIndex+d.img.YStride*0x8, 1, d.img.YStride, true)
- filter246(d.img.Y, 16, l, il, hl, yIndex+d.img.YStride*0xc, 1, d.img.YStride, true)
- filter246(d.img.Cb, 8, l, il, hl, cIndex+d.img.CStride*0x4, 1, d.img.CStride, true)
- filter246(d.img.Cr, 8, l, il, hl, cIndex+d.img.CStride*0x4, 1, d.img.CStride, true)
- }
- }
- }
-}
-
-// filterParam holds the loop filter parameters for a macroblock.
-type filterParam struct {
- // The first three fields are thresholds used by the loop filter to smooth
- // over the edges and interior of a macroblock. level is used by both the
- // simple and normal filters. The inner level and high edge variance level
- // are only used by the normal filter.
- level, ilevel, hlevel uint8
- // inner is whether the inner loop filter cannot be optimized out as a
- // no-op for this particular macroblock.
- inner bool
-}
-
-// computeFilterParams computes the loop filter parameters, as specified in
-// section 15.4.
-func (d *Decoder) computeFilterParams() {
- for i := range d.filterParams {
- baseLevel := d.filterHeader.level
- if d.segmentHeader.useSegment {
- baseLevel = d.segmentHeader.filterStrength[i]
- if d.segmentHeader.relativeDelta {
- baseLevel += d.filterHeader.level
- }
- }
-
- for j := range d.filterParams[i] {
- p := &d.filterParams[i][j]
- p.inner = j != 0
- level := baseLevel
- if d.filterHeader.useLFDelta {
- // The libwebp C code has a "TODO: only CURRENT is handled for now."
- level += d.filterHeader.refLFDelta[0]
- if j != 0 {
- level += d.filterHeader.modeLFDelta[0]
- }
- }
- if level <= 0 {
- p.level = 0
- continue
- }
- if level > 63 {
- level = 63
- }
- ilevel := level
- if d.filterHeader.sharpness > 0 {
- if d.filterHeader.sharpness > 4 {
- ilevel >>= 2
- } else {
- ilevel >>= 1
- }
- if x := int8(9 - d.filterHeader.sharpness); ilevel > x {
- ilevel = x
- }
- }
- if ilevel < 1 {
- ilevel = 1
- }
- p.ilevel = uint8(ilevel)
- p.level = uint8(2*level + ilevel)
- if d.frameHeader.KeyFrame {
- if level < 15 {
- p.hlevel = 0
- } else if level < 40 {
- p.hlevel = 1
- } else {
- p.hlevel = 2
- }
- } else {
- if level < 15 {
- p.hlevel = 0
- } else if level < 20 {
- p.hlevel = 1
- } else if level < 40 {
- p.hlevel = 2
- } else {
- p.hlevel = 3
- }
- }
- }
- }
-}
-
-// intSize is either 32 or 64.
-const intSize = 32 << (^uint(0) >> 63)
-
-func abs(x int) int {
- // m := -1 if x < 0. m := 0 otherwise.
- m := x >> (intSize - 1)
-
- // In two's complement representation, the negative number
- // of any number (except the smallest one) can be computed
- // by flipping all the bits and add 1. This is faster than
- // code with a branch.
- // See Hacker's Delight, section 2-4.
- return (x ^ m) - m
-}
-
-func clamp15(x int) int {
- if x < -16 {
- return -16
- }
- if x > 15 {
- return 15
- }
- return x
-}
-
-func clamp127(x int) int {
- if x < -128 {
- return -128
- }
- if x > 127 {
- return 127
- }
- return x
-}
-
-func clamp255(x int) uint8 {
- if x < 0 {
- return 0
- }
- if x > 255 {
- return 255
- }
- return uint8(x)
-}
diff --git a/vendor/golang.org/x/image/vp8/idct.go b/vendor/golang.org/x/image/vp8/idct.go
deleted file mode 100644
index 929af2c..0000000
--- a/vendor/golang.org/x/image/vp8/idct.go
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package vp8
-
-// This file implements the inverse Discrete Cosine Transform and the inverse
-// Walsh Hadamard Transform (WHT), as specified in sections 14.3 and 14.4.
-
-func clip8(i int32) uint8 {
- if i < 0 {
- return 0
- }
- if i > 255 {
- return 255
- }
- return uint8(i)
-}
-
-func (z *Decoder) inverseDCT4(y, x, coeffBase int) {
- const (
- c1 = 85627 // 65536 * cos(pi/8) * sqrt(2).
- c2 = 35468 // 65536 * sin(pi/8) * sqrt(2).
- )
- var m [4][4]int32
- for i := 0; i < 4; i++ {
- a := int32(z.coeff[coeffBase+0]) + int32(z.coeff[coeffBase+8])
- b := int32(z.coeff[coeffBase+0]) - int32(z.coeff[coeffBase+8])
- c := (int32(z.coeff[coeffBase+4])*c2)>>16 - (int32(z.coeff[coeffBase+12])*c1)>>16
- d := (int32(z.coeff[coeffBase+4])*c1)>>16 + (int32(z.coeff[coeffBase+12])*c2)>>16
- m[i][0] = a + d
- m[i][1] = b + c
- m[i][2] = b - c
- m[i][3] = a - d
- coeffBase++
- }
- for j := 0; j < 4; j++ {
- dc := m[0][j] + 4
- a := dc + m[2][j]
- b := dc - m[2][j]
- c := (m[1][j]*c2)>>16 - (m[3][j]*c1)>>16
- d := (m[1][j]*c1)>>16 + (m[3][j]*c2)>>16
- z.ybr[y+j][x+0] = clip8(int32(z.ybr[y+j][x+0]) + (a+d)>>3)
- z.ybr[y+j][x+1] = clip8(int32(z.ybr[y+j][x+1]) + (b+c)>>3)
- z.ybr[y+j][x+2] = clip8(int32(z.ybr[y+j][x+2]) + (b-c)>>3)
- z.ybr[y+j][x+3] = clip8(int32(z.ybr[y+j][x+3]) + (a-d)>>3)
- }
-}
-
-func (z *Decoder) inverseDCT4DCOnly(y, x, coeffBase int) {
- dc := (int32(z.coeff[coeffBase+0]) + 4) >> 3
- for j := 0; j < 4; j++ {
- for i := 0; i < 4; i++ {
- z.ybr[y+j][x+i] = clip8(int32(z.ybr[y+j][x+i]) + dc)
- }
- }
-}
-
-func (z *Decoder) inverseDCT8(y, x, coeffBase int) {
- z.inverseDCT4(y+0, x+0, coeffBase+0*16)
- z.inverseDCT4(y+0, x+4, coeffBase+1*16)
- z.inverseDCT4(y+4, x+0, coeffBase+2*16)
- z.inverseDCT4(y+4, x+4, coeffBase+3*16)
-}
-
-func (z *Decoder) inverseDCT8DCOnly(y, x, coeffBase int) {
- z.inverseDCT4DCOnly(y+0, x+0, coeffBase+0*16)
- z.inverseDCT4DCOnly(y+0, x+4, coeffBase+1*16)
- z.inverseDCT4DCOnly(y+4, x+0, coeffBase+2*16)
- z.inverseDCT4DCOnly(y+4, x+4, coeffBase+3*16)
-}
-
-func (d *Decoder) inverseWHT16() {
- var m [16]int32
- for i := 0; i < 4; i++ {
- a0 := int32(d.coeff[384+0+i]) + int32(d.coeff[384+12+i])
- a1 := int32(d.coeff[384+4+i]) + int32(d.coeff[384+8+i])
- a2 := int32(d.coeff[384+4+i]) - int32(d.coeff[384+8+i])
- a3 := int32(d.coeff[384+0+i]) - int32(d.coeff[384+12+i])
- m[0+i] = a0 + a1
- m[8+i] = a0 - a1
- m[4+i] = a3 + a2
- m[12+i] = a3 - a2
- }
- out := 0
- for i := 0; i < 4; i++ {
- dc := m[0+i*4] + 3
- a0 := dc + m[3+i*4]
- a1 := m[1+i*4] + m[2+i*4]
- a2 := m[1+i*4] - m[2+i*4]
- a3 := dc - m[3+i*4]
- d.coeff[out+0] = int16((a0 + a1) >> 3)
- d.coeff[out+16] = int16((a3 + a2) >> 3)
- d.coeff[out+32] = int16((a0 - a1) >> 3)
- d.coeff[out+48] = int16((a3 - a2) >> 3)
- out += 64
- }
-}
diff --git a/vendor/golang.org/x/image/vp8/partition.go b/vendor/golang.org/x/image/vp8/partition.go
deleted file mode 100644
index 72288bd..0000000
--- a/vendor/golang.org/x/image/vp8/partition.go
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package vp8
-
-// Each VP8 frame consists of between 2 and 9 bitstream partitions.
-// Each partition is byte-aligned and is independently arithmetic-encoded.
-//
-// This file implements decoding a partition's bitstream, as specified in
-// chapter 7. The implementation follows libwebp's approach instead of the
-// specification's reference C implementation. For example, we use a look-up
-// table instead of a for loop to recalibrate the encoded range.
-
-var (
- lutShift = [127]uint8{
- 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- }
- lutRangeM1 = [127]uint8{
- 127,
- 127, 191,
- 127, 159, 191, 223,
- 127, 143, 159, 175, 191, 207, 223, 239,
- 127, 135, 143, 151, 159, 167, 175, 183, 191, 199, 207, 215, 223, 231, 239, 247,
- 127, 131, 135, 139, 143, 147, 151, 155, 159, 163, 167, 171, 175, 179, 183, 187,
- 191, 195, 199, 203, 207, 211, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251,
- 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 157,
- 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189,
- 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221,
- 223, 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253,
- }
-)
-
-// uniformProb represents a 50% probability that the next bit is 0.
-const uniformProb = 128
-
-// partition holds arithmetic-coded bits.
-type partition struct {
- // buf is the input bytes.
- buf []byte
- // r is how many of buf's bytes have been consumed.
- r int
- // rangeM1 is range minus 1, where range is in the arithmetic coding sense,
- // not the Go language sense.
- rangeM1 uint32
- // bits and nBits hold those bits shifted out of buf but not yet consumed.
- bits uint32
- nBits uint8
- // unexpectedEOF tells whether we tried to read past buf.
- unexpectedEOF bool
-}
-
-// init initializes the partition.
-func (p *partition) init(buf []byte) {
- p.buf = buf
- p.r = 0
- p.rangeM1 = 254
- p.bits = 0
- p.nBits = 0
- p.unexpectedEOF = false
-}
-
-// readBit returns the next bit.
-func (p *partition) readBit(prob uint8) bool {
- if p.nBits < 8 {
- if p.r >= len(p.buf) {
- p.unexpectedEOF = true
- return false
- }
- // Expression split for 386 compiler.
- x := uint32(p.buf[p.r])
- p.bits |= x << (8 - p.nBits)
- p.r++
- p.nBits += 8
- }
- split := (p.rangeM1*uint32(prob))>>8 + 1
- bit := p.bits >= split<<8
- if bit {
- p.rangeM1 -= split
- p.bits -= split << 8
- } else {
- p.rangeM1 = split - 1
- }
- if p.rangeM1 < 127 {
- shift := lutShift[p.rangeM1]
- p.rangeM1 = uint32(lutRangeM1[p.rangeM1])
- p.bits <<= shift
- p.nBits -= shift
- }
- return bit
-}
-
-// readUint returns the next n-bit unsigned integer.
-func (p *partition) readUint(prob, n uint8) uint32 {
- var u uint32
- for n > 0 {
- n--
- if p.readBit(prob) {
- u |= 1 << n
- }
- }
- return u
-}
-
-// readInt returns the next n-bit signed integer.
-func (p *partition) readInt(prob, n uint8) int32 {
- u := p.readUint(prob, n)
- b := p.readBit(prob)
- if b {
- return -int32(u)
- }
- return int32(u)
-}
-
-// readOptionalInt returns the next n-bit signed integer in an encoding
-// where the likely result is zero.
-func (p *partition) readOptionalInt(prob, n uint8) int32 {
- if !p.readBit(prob) {
- return 0
- }
- return p.readInt(prob, n)
-}
diff --git a/vendor/golang.org/x/image/vp8/pred.go b/vendor/golang.org/x/image/vp8/pred.go
deleted file mode 100644
index 58c2689..0000000
--- a/vendor/golang.org/x/image/vp8/pred.go
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package vp8
-
-// This file implements parsing the predictor modes, as specified in chapter
-// 11.
-
-func (d *Decoder) parsePredModeY16(mbx int) {
- var p uint8
- if !d.fp.readBit(156) {
- if !d.fp.readBit(163) {
- p = predDC
- } else {
- p = predVE
- }
- } else if !d.fp.readBit(128) {
- p = predHE
- } else {
- p = predTM
- }
- for i := 0; i < 4; i++ {
- d.upMB[mbx].pred[i] = p
- d.leftMB.pred[i] = p
- }
- d.predY16 = p
-}
-
-func (d *Decoder) parsePredModeC8() {
- if !d.fp.readBit(142) {
- d.predC8 = predDC
- } else if !d.fp.readBit(114) {
- d.predC8 = predVE
- } else if !d.fp.readBit(183) {
- d.predC8 = predHE
- } else {
- d.predC8 = predTM
- }
-}
-
-func (d *Decoder) parsePredModeY4(mbx int) {
- for j := 0; j < 4; j++ {
- p := d.leftMB.pred[j]
- for i := 0; i < 4; i++ {
- prob := &predProb[d.upMB[mbx].pred[i]][p]
- if !d.fp.readBit(prob[0]) {
- p = predDC
- } else if !d.fp.readBit(prob[1]) {
- p = predTM
- } else if !d.fp.readBit(prob[2]) {
- p = predVE
- } else if !d.fp.readBit(prob[3]) {
- if !d.fp.readBit(prob[4]) {
- p = predHE
- } else if !d.fp.readBit(prob[5]) {
- p = predRD
- } else {
- p = predVR
- }
- } else if !d.fp.readBit(prob[6]) {
- p = predLD
- } else if !d.fp.readBit(prob[7]) {
- p = predVL
- } else if !d.fp.readBit(prob[8]) {
- p = predHD
- } else {
- p = predHU
- }
- d.predY4[j][i] = p
- d.upMB[mbx].pred[i] = p
- }
- d.leftMB.pred[j] = p
- }
-}
-
-// predProb are the probabilities to decode a 4x4 region's predictor mode given
-// the predictor modes of the regions above and left of it.
-// These values are specified in section 11.5.
-var predProb = [nPred][nPred][9]uint8{
- {
- {231, 120, 48, 89, 115, 113, 120, 152, 112},
- {152, 179, 64, 126, 170, 118, 46, 70, 95},
- {175, 69, 143, 80, 85, 82, 72, 155, 103},
- {56, 58, 10, 171, 218, 189, 17, 13, 152},
- {114, 26, 17, 163, 44, 195, 21, 10, 173},
- {121, 24, 80, 195, 26, 62, 44, 64, 85},
- {144, 71, 10, 38, 171, 213, 144, 34, 26},
- {170, 46, 55, 19, 136, 160, 33, 206, 71},
- {63, 20, 8, 114, 114, 208, 12, 9, 226},
- {81, 40, 11, 96, 182, 84, 29, 16, 36},
- },
- {
- {134, 183, 89, 137, 98, 101, 106, 165, 148},
- {72, 187, 100, 130, 157, 111, 32, 75, 80},
- {66, 102, 167, 99, 74, 62, 40, 234, 128},
- {41, 53, 9, 178, 241, 141, 26, 8, 107},
- {74, 43, 26, 146, 73, 166, 49, 23, 157},
- {65, 38, 105, 160, 51, 52, 31, 115, 128},
- {104, 79, 12, 27, 217, 255, 87, 17, 7},
- {87, 68, 71, 44, 114, 51, 15, 186, 23},
- {47, 41, 14, 110, 182, 183, 21, 17, 194},
- {66, 45, 25, 102, 197, 189, 23, 18, 22},
- },
- {
- {88, 88, 147, 150, 42, 46, 45, 196, 205},
- {43, 97, 183, 117, 85, 38, 35, 179, 61},
- {39, 53, 200, 87, 26, 21, 43, 232, 171},
- {56, 34, 51, 104, 114, 102, 29, 93, 77},
- {39, 28, 85, 171, 58, 165, 90, 98, 64},
- {34, 22, 116, 206, 23, 34, 43, 166, 73},
- {107, 54, 32, 26, 51, 1, 81, 43, 31},
- {68, 25, 106, 22, 64, 171, 36, 225, 114},
- {34, 19, 21, 102, 132, 188, 16, 76, 124},
- {62, 18, 78, 95, 85, 57, 50, 48, 51},
- },
- {
- {193, 101, 35, 159, 215, 111, 89, 46, 111},
- {60, 148, 31, 172, 219, 228, 21, 18, 111},
- {112, 113, 77, 85, 179, 255, 38, 120, 114},
- {40, 42, 1, 196, 245, 209, 10, 25, 109},
- {88, 43, 29, 140, 166, 213, 37, 43, 154},
- {61, 63, 30, 155, 67, 45, 68, 1, 209},
- {100, 80, 8, 43, 154, 1, 51, 26, 71},
- {142, 78, 78, 16, 255, 128, 34, 197, 171},
- {41, 40, 5, 102, 211, 183, 4, 1, 221},
- {51, 50, 17, 168, 209, 192, 23, 25, 82},
- },
- {
- {138, 31, 36, 171, 27, 166, 38, 44, 229},
- {67, 87, 58, 169, 82, 115, 26, 59, 179},
- {63, 59, 90, 180, 59, 166, 93, 73, 154},
- {40, 40, 21, 116, 143, 209, 34, 39, 175},
- {47, 15, 16, 183, 34, 223, 49, 45, 183},
- {46, 17, 33, 183, 6, 98, 15, 32, 183},
- {57, 46, 22, 24, 128, 1, 54, 17, 37},
- {65, 32, 73, 115, 28, 128, 23, 128, 205},
- {40, 3, 9, 115, 51, 192, 18, 6, 223},
- {87, 37, 9, 115, 59, 77, 64, 21, 47},
- },
- {
- {104, 55, 44, 218, 9, 54, 53, 130, 226},
- {64, 90, 70, 205, 40, 41, 23, 26, 57},
- {54, 57, 112, 184, 5, 41, 38, 166, 213},
- {30, 34, 26, 133, 152, 116, 10, 32, 134},
- {39, 19, 53, 221, 26, 114, 32, 73, 255},
- {31, 9, 65, 234, 2, 15, 1, 118, 73},
- {75, 32, 12, 51, 192, 255, 160, 43, 51},
- {88, 31, 35, 67, 102, 85, 55, 186, 85},
- {56, 21, 23, 111, 59, 205, 45, 37, 192},
- {55, 38, 70, 124, 73, 102, 1, 34, 98},
- },
- {
- {125, 98, 42, 88, 104, 85, 117, 175, 82},
- {95, 84, 53, 89, 128, 100, 113, 101, 45},
- {75, 79, 123, 47, 51, 128, 81, 171, 1},
- {57, 17, 5, 71, 102, 57, 53, 41, 49},
- {38, 33, 13, 121, 57, 73, 26, 1, 85},
- {41, 10, 67, 138, 77, 110, 90, 47, 114},
- {115, 21, 2, 10, 102, 255, 166, 23, 6},
- {101, 29, 16, 10, 85, 128, 101, 196, 26},
- {57, 18, 10, 102, 102, 213, 34, 20, 43},
- {117, 20, 15, 36, 163, 128, 68, 1, 26},
- },
- {
- {102, 61, 71, 37, 34, 53, 31, 243, 192},
- {69, 60, 71, 38, 73, 119, 28, 222, 37},
- {68, 45, 128, 34, 1, 47, 11, 245, 171},
- {62, 17, 19, 70, 146, 85, 55, 62, 70},
- {37, 43, 37, 154, 100, 163, 85, 160, 1},
- {63, 9, 92, 136, 28, 64, 32, 201, 85},
- {75, 15, 9, 9, 64, 255, 184, 119, 16},
- {86, 6, 28, 5, 64, 255, 25, 248, 1},
- {56, 8, 17, 132, 137, 255, 55, 116, 128},
- {58, 15, 20, 82, 135, 57, 26, 121, 40},
- },
- {
- {164, 50, 31, 137, 154, 133, 25, 35, 218},
- {51, 103, 44, 131, 131, 123, 31, 6, 158},
- {86, 40, 64, 135, 148, 224, 45, 183, 128},
- {22, 26, 17, 131, 240, 154, 14, 1, 209},
- {45, 16, 21, 91, 64, 222, 7, 1, 197},
- {56, 21, 39, 155, 60, 138, 23, 102, 213},
- {83, 12, 13, 54, 192, 255, 68, 47, 28},
- {85, 26, 85, 85, 128, 128, 32, 146, 171},
- {18, 11, 7, 63, 144, 171, 4, 4, 246},
- {35, 27, 10, 146, 174, 171, 12, 26, 128},
- },
- {
- {190, 80, 35, 99, 180, 80, 126, 54, 45},
- {85, 126, 47, 87, 176, 51, 41, 20, 32},
- {101, 75, 128, 139, 118, 146, 116, 128, 85},
- {56, 41, 15, 176, 236, 85, 37, 9, 62},
- {71, 30, 17, 119, 118, 255, 17, 18, 138},
- {101, 38, 60, 138, 55, 70, 43, 26, 142},
- {146, 36, 19, 30, 171, 255, 97, 27, 20},
- {138, 45, 61, 62, 219, 1, 81, 188, 64},
- {32, 41, 20, 117, 151, 142, 20, 21, 163},
- {112, 19, 12, 61, 195, 128, 48, 4, 24},
- },
-}
diff --git a/vendor/golang.org/x/image/vp8/predfunc.go b/vendor/golang.org/x/image/vp8/predfunc.go
deleted file mode 100644
index f899958..0000000
--- a/vendor/golang.org/x/image/vp8/predfunc.go
+++ /dev/null
@@ -1,553 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package vp8
-
-// This file implements the predicition functions, as specified in chapter 12.
-//
-// For each macroblock (of 1x16x16 luma and 2x8x8 chroma coefficients), the
-// luma values are either predicted as one large 16x16 region or 16 separate
-// 4x4 regions. The chroma values are always predicted as one 8x8 region.
-//
-// For 4x4 regions, the target block's predicted values (Xs) are a function of
-// its previously-decoded top and left border values, as well as a number of
-// pixels from the top-right:
-//
-// a b c d e f g h
-// p X X X X
-// q X X X X
-// r X X X X
-// s X X X X
-//
-// The predictor modes are:
-// - DC: all Xs = (b + c + d + e + p + q + r + s + 4) / 8.
-// - TM: the first X = (b + p - a), the second X = (c + p - a), and so on.
-// - VE: each X = the weighted average of its column's top value and that
-// value's neighbors, i.e. averages of abc, bcd, cde or def.
-// - HE: similar to VE except rows instead of columns, and the final row is
-// an average of r, s and s.
-// - RD, VR, LD, VL, HD, HU: these diagonal modes ("Right Down", "Vertical
-// Right", etc) are more complicated and are described in section 12.3.
-// All Xs are clipped to the range [0, 255].
-//
-// For 8x8 and 16x16 regions, the target block's predicted values are a
-// function of the top and left border values without the top-right overhang,
-// i.e. without the 8x8 or 16x16 equivalent of f, g and h. Furthermore:
-// - There are no diagonal predictor modes, only DC, TM, VE and HE.
-// - The DC mode has variants for macroblocks in the top row and/or left
-// column, i.e. for macroblocks with mby == 0 || mbx == 0.
-// - The VE and HE modes take only the column top or row left values; they do
-// not smooth that top/left value with its neighbors.
-
-// nPred is the number of predictor modes, not including the Top/Left versions
-// of the DC predictor mode.
-const nPred = 10
-
-const (
- predDC = iota
- predTM
- predVE
- predHE
- predRD
- predVR
- predLD
- predVL
- predHD
- predHU
- predDCTop
- predDCLeft
- predDCTopLeft
-)
-
-func checkTopLeftPred(mbx, mby int, p uint8) uint8 {
- if p != predDC {
- return p
- }
- if mbx == 0 {
- if mby == 0 {
- return predDCTopLeft
- }
- return predDCLeft
- }
- if mby == 0 {
- return predDCTop
- }
- return predDC
-}
-
-var predFunc4 = [...]func(*Decoder, int, int){
- predFunc4DC,
- predFunc4TM,
- predFunc4VE,
- predFunc4HE,
- predFunc4RD,
- predFunc4VR,
- predFunc4LD,
- predFunc4VL,
- predFunc4HD,
- predFunc4HU,
- nil,
- nil,
- nil,
-}
-
-var predFunc8 = [...]func(*Decoder, int, int){
- predFunc8DC,
- predFunc8TM,
- predFunc8VE,
- predFunc8HE,
- nil,
- nil,
- nil,
- nil,
- nil,
- nil,
- predFunc8DCTop,
- predFunc8DCLeft,
- predFunc8DCTopLeft,
-}
-
-var predFunc16 = [...]func(*Decoder, int, int){
- predFunc16DC,
- predFunc16TM,
- predFunc16VE,
- predFunc16HE,
- nil,
- nil,
- nil,
- nil,
- nil,
- nil,
- predFunc16DCTop,
- predFunc16DCLeft,
- predFunc16DCTopLeft,
-}
-
-func predFunc4DC(z *Decoder, y, x int) {
- sum := uint32(4)
- for i := 0; i < 4; i++ {
- sum += uint32(z.ybr[y-1][x+i])
- }
- for j := 0; j < 4; j++ {
- sum += uint32(z.ybr[y+j][x-1])
- }
- avg := uint8(sum / 8)
- for j := 0; j < 4; j++ {
- for i := 0; i < 4; i++ {
- z.ybr[y+j][x+i] = avg
- }
- }
-}
-
-func predFunc4TM(z *Decoder, y, x int) {
- delta0 := -int32(z.ybr[y-1][x-1])
- for j := 0; j < 4; j++ {
- delta1 := delta0 + int32(z.ybr[y+j][x-1])
- for i := 0; i < 4; i++ {
- delta2 := delta1 + int32(z.ybr[y-1][x+i])
- z.ybr[y+j][x+i] = uint8(clip(delta2, 0, 255))
- }
- }
-}
-
-func predFunc4VE(z *Decoder, y, x int) {
- a := int32(z.ybr[y-1][x-1])
- b := int32(z.ybr[y-1][x+0])
- c := int32(z.ybr[y-1][x+1])
- d := int32(z.ybr[y-1][x+2])
- e := int32(z.ybr[y-1][x+3])
- f := int32(z.ybr[y-1][x+4])
- abc := uint8((a + 2*b + c + 2) / 4)
- bcd := uint8((b + 2*c + d + 2) / 4)
- cde := uint8((c + 2*d + e + 2) / 4)
- def := uint8((d + 2*e + f + 2) / 4)
- for j := 0; j < 4; j++ {
- z.ybr[y+j][x+0] = abc
- z.ybr[y+j][x+1] = bcd
- z.ybr[y+j][x+2] = cde
- z.ybr[y+j][x+3] = def
- }
-}
-
-func predFunc4HE(z *Decoder, y, x int) {
- s := int32(z.ybr[y+3][x-1])
- r := int32(z.ybr[y+2][x-1])
- q := int32(z.ybr[y+1][x-1])
- p := int32(z.ybr[y+0][x-1])
- a := int32(z.ybr[y-1][x-1])
- ssr := uint8((s + 2*s + r + 2) / 4)
- srq := uint8((s + 2*r + q + 2) / 4)
- rqp := uint8((r + 2*q + p + 2) / 4)
- apq := uint8((a + 2*p + q + 2) / 4)
- for i := 0; i < 4; i++ {
- z.ybr[y+0][x+i] = apq
- z.ybr[y+1][x+i] = rqp
- z.ybr[y+2][x+i] = srq
- z.ybr[y+3][x+i] = ssr
- }
-}
-
-func predFunc4RD(z *Decoder, y, x int) {
- s := int32(z.ybr[y+3][x-1])
- r := int32(z.ybr[y+2][x-1])
- q := int32(z.ybr[y+1][x-1])
- p := int32(z.ybr[y+0][x-1])
- a := int32(z.ybr[y-1][x-1])
- b := int32(z.ybr[y-1][x+0])
- c := int32(z.ybr[y-1][x+1])
- d := int32(z.ybr[y-1][x+2])
- e := int32(z.ybr[y-1][x+3])
- srq := uint8((s + 2*r + q + 2) / 4)
- rqp := uint8((r + 2*q + p + 2) / 4)
- qpa := uint8((q + 2*p + a + 2) / 4)
- pab := uint8((p + 2*a + b + 2) / 4)
- abc := uint8((a + 2*b + c + 2) / 4)
- bcd := uint8((b + 2*c + d + 2) / 4)
- cde := uint8((c + 2*d + e + 2) / 4)
- z.ybr[y+0][x+0] = pab
- z.ybr[y+0][x+1] = abc
- z.ybr[y+0][x+2] = bcd
- z.ybr[y+0][x+3] = cde
- z.ybr[y+1][x+0] = qpa
- z.ybr[y+1][x+1] = pab
- z.ybr[y+1][x+2] = abc
- z.ybr[y+1][x+3] = bcd
- z.ybr[y+2][x+0] = rqp
- z.ybr[y+2][x+1] = qpa
- z.ybr[y+2][x+2] = pab
- z.ybr[y+2][x+3] = abc
- z.ybr[y+3][x+0] = srq
- z.ybr[y+3][x+1] = rqp
- z.ybr[y+3][x+2] = qpa
- z.ybr[y+3][x+3] = pab
-}
-
-func predFunc4VR(z *Decoder, y, x int) {
- r := int32(z.ybr[y+2][x-1])
- q := int32(z.ybr[y+1][x-1])
- p := int32(z.ybr[y+0][x-1])
- a := int32(z.ybr[y-1][x-1])
- b := int32(z.ybr[y-1][x+0])
- c := int32(z.ybr[y-1][x+1])
- d := int32(z.ybr[y-1][x+2])
- e := int32(z.ybr[y-1][x+3])
- ab := uint8((a + b + 1) / 2)
- bc := uint8((b + c + 1) / 2)
- cd := uint8((c + d + 1) / 2)
- de := uint8((d + e + 1) / 2)
- rqp := uint8((r + 2*q + p + 2) / 4)
- qpa := uint8((q + 2*p + a + 2) / 4)
- pab := uint8((p + 2*a + b + 2) / 4)
- abc := uint8((a + 2*b + c + 2) / 4)
- bcd := uint8((b + 2*c + d + 2) / 4)
- cde := uint8((c + 2*d + e + 2) / 4)
- z.ybr[y+0][x+0] = ab
- z.ybr[y+0][x+1] = bc
- z.ybr[y+0][x+2] = cd
- z.ybr[y+0][x+3] = de
- z.ybr[y+1][x+0] = pab
- z.ybr[y+1][x+1] = abc
- z.ybr[y+1][x+2] = bcd
- z.ybr[y+1][x+3] = cde
- z.ybr[y+2][x+0] = qpa
- z.ybr[y+2][x+1] = ab
- z.ybr[y+2][x+2] = bc
- z.ybr[y+2][x+3] = cd
- z.ybr[y+3][x+0] = rqp
- z.ybr[y+3][x+1] = pab
- z.ybr[y+3][x+2] = abc
- z.ybr[y+3][x+3] = bcd
-}
-
-func predFunc4LD(z *Decoder, y, x int) {
- a := int32(z.ybr[y-1][x+0])
- b := int32(z.ybr[y-1][x+1])
- c := int32(z.ybr[y-1][x+2])
- d := int32(z.ybr[y-1][x+3])
- e := int32(z.ybr[y-1][x+4])
- f := int32(z.ybr[y-1][x+5])
- g := int32(z.ybr[y-1][x+6])
- h := int32(z.ybr[y-1][x+7])
- abc := uint8((a + 2*b + c + 2) / 4)
- bcd := uint8((b + 2*c + d + 2) / 4)
- cde := uint8((c + 2*d + e + 2) / 4)
- def := uint8((d + 2*e + f + 2) / 4)
- efg := uint8((e + 2*f + g + 2) / 4)
- fgh := uint8((f + 2*g + h + 2) / 4)
- ghh := uint8((g + 2*h + h + 2) / 4)
- z.ybr[y+0][x+0] = abc
- z.ybr[y+0][x+1] = bcd
- z.ybr[y+0][x+2] = cde
- z.ybr[y+0][x+3] = def
- z.ybr[y+1][x+0] = bcd
- z.ybr[y+1][x+1] = cde
- z.ybr[y+1][x+2] = def
- z.ybr[y+1][x+3] = efg
- z.ybr[y+2][x+0] = cde
- z.ybr[y+2][x+1] = def
- z.ybr[y+2][x+2] = efg
- z.ybr[y+2][x+3] = fgh
- z.ybr[y+3][x+0] = def
- z.ybr[y+3][x+1] = efg
- z.ybr[y+3][x+2] = fgh
- z.ybr[y+3][x+3] = ghh
-}
-
-func predFunc4VL(z *Decoder, y, x int) {
- a := int32(z.ybr[y-1][x+0])
- b := int32(z.ybr[y-1][x+1])
- c := int32(z.ybr[y-1][x+2])
- d := int32(z.ybr[y-1][x+3])
- e := int32(z.ybr[y-1][x+4])
- f := int32(z.ybr[y-1][x+5])
- g := int32(z.ybr[y-1][x+6])
- h := int32(z.ybr[y-1][x+7])
- ab := uint8((a + b + 1) / 2)
- bc := uint8((b + c + 1) / 2)
- cd := uint8((c + d + 1) / 2)
- de := uint8((d + e + 1) / 2)
- abc := uint8((a + 2*b + c + 2) / 4)
- bcd := uint8((b + 2*c + d + 2) / 4)
- cde := uint8((c + 2*d + e + 2) / 4)
- def := uint8((d + 2*e + f + 2) / 4)
- efg := uint8((e + 2*f + g + 2) / 4)
- fgh := uint8((f + 2*g + h + 2) / 4)
- z.ybr[y+0][x+0] = ab
- z.ybr[y+0][x+1] = bc
- z.ybr[y+0][x+2] = cd
- z.ybr[y+0][x+3] = de
- z.ybr[y+1][x+0] = abc
- z.ybr[y+1][x+1] = bcd
- z.ybr[y+1][x+2] = cde
- z.ybr[y+1][x+3] = def
- z.ybr[y+2][x+0] = bc
- z.ybr[y+2][x+1] = cd
- z.ybr[y+2][x+2] = de
- z.ybr[y+2][x+3] = efg
- z.ybr[y+3][x+0] = bcd
- z.ybr[y+3][x+1] = cde
- z.ybr[y+3][x+2] = def
- z.ybr[y+3][x+3] = fgh
-}
-
-func predFunc4HD(z *Decoder, y, x int) {
- s := int32(z.ybr[y+3][x-1])
- r := int32(z.ybr[y+2][x-1])
- q := int32(z.ybr[y+1][x-1])
- p := int32(z.ybr[y+0][x-1])
- a := int32(z.ybr[y-1][x-1])
- b := int32(z.ybr[y-1][x+0])
- c := int32(z.ybr[y-1][x+1])
- d := int32(z.ybr[y-1][x+2])
- sr := uint8((s + r + 1) / 2)
- rq := uint8((r + q + 1) / 2)
- qp := uint8((q + p + 1) / 2)
- pa := uint8((p + a + 1) / 2)
- srq := uint8((s + 2*r + q + 2) / 4)
- rqp := uint8((r + 2*q + p + 2) / 4)
- qpa := uint8((q + 2*p + a + 2) / 4)
- pab := uint8((p + 2*a + b + 2) / 4)
- abc := uint8((a + 2*b + c + 2) / 4)
- bcd := uint8((b + 2*c + d + 2) / 4)
- z.ybr[y+0][x+0] = pa
- z.ybr[y+0][x+1] = pab
- z.ybr[y+0][x+2] = abc
- z.ybr[y+0][x+3] = bcd
- z.ybr[y+1][x+0] = qp
- z.ybr[y+1][x+1] = qpa
- z.ybr[y+1][x+2] = pa
- z.ybr[y+1][x+3] = pab
- z.ybr[y+2][x+0] = rq
- z.ybr[y+2][x+1] = rqp
- z.ybr[y+2][x+2] = qp
- z.ybr[y+2][x+3] = qpa
- z.ybr[y+3][x+0] = sr
- z.ybr[y+3][x+1] = srq
- z.ybr[y+3][x+2] = rq
- z.ybr[y+3][x+3] = rqp
-}
-
-func predFunc4HU(z *Decoder, y, x int) {
- s := int32(z.ybr[y+3][x-1])
- r := int32(z.ybr[y+2][x-1])
- q := int32(z.ybr[y+1][x-1])
- p := int32(z.ybr[y+0][x-1])
- pq := uint8((p + q + 1) / 2)
- qr := uint8((q + r + 1) / 2)
- rs := uint8((r + s + 1) / 2)
- pqr := uint8((p + 2*q + r + 2) / 4)
- qrs := uint8((q + 2*r + s + 2) / 4)
- rss := uint8((r + 2*s + s + 2) / 4)
- sss := uint8(s)
- z.ybr[y+0][x+0] = pq
- z.ybr[y+0][x+1] = pqr
- z.ybr[y+0][x+2] = qr
- z.ybr[y+0][x+3] = qrs
- z.ybr[y+1][x+0] = qr
- z.ybr[y+1][x+1] = qrs
- z.ybr[y+1][x+2] = rs
- z.ybr[y+1][x+3] = rss
- z.ybr[y+2][x+0] = rs
- z.ybr[y+2][x+1] = rss
- z.ybr[y+2][x+2] = sss
- z.ybr[y+2][x+3] = sss
- z.ybr[y+3][x+0] = sss
- z.ybr[y+3][x+1] = sss
- z.ybr[y+3][x+2] = sss
- z.ybr[y+3][x+3] = sss
-}
-
-func predFunc8DC(z *Decoder, y, x int) {
- sum := uint32(8)
- for i := 0; i < 8; i++ {
- sum += uint32(z.ybr[y-1][x+i])
- }
- for j := 0; j < 8; j++ {
- sum += uint32(z.ybr[y+j][x-1])
- }
- avg := uint8(sum / 16)
- for j := 0; j < 8; j++ {
- for i := 0; i < 8; i++ {
- z.ybr[y+j][x+i] = avg
- }
- }
-}
-
-func predFunc8TM(z *Decoder, y, x int) {
- delta0 := -int32(z.ybr[y-1][x-1])
- for j := 0; j < 8; j++ {
- delta1 := delta0 + int32(z.ybr[y+j][x-1])
- for i := 0; i < 8; i++ {
- delta2 := delta1 + int32(z.ybr[y-1][x+i])
- z.ybr[y+j][x+i] = uint8(clip(delta2, 0, 255))
- }
- }
-}
-
-func predFunc8VE(z *Decoder, y, x int) {
- for j := 0; j < 8; j++ {
- for i := 0; i < 8; i++ {
- z.ybr[y+j][x+i] = z.ybr[y-1][x+i]
- }
- }
-}
-
-func predFunc8HE(z *Decoder, y, x int) {
- for j := 0; j < 8; j++ {
- for i := 0; i < 8; i++ {
- z.ybr[y+j][x+i] = z.ybr[y+j][x-1]
- }
- }
-}
-
-func predFunc8DCTop(z *Decoder, y, x int) {
- sum := uint32(4)
- for j := 0; j < 8; j++ {
- sum += uint32(z.ybr[y+j][x-1])
- }
- avg := uint8(sum / 8)
- for j := 0; j < 8; j++ {
- for i := 0; i < 8; i++ {
- z.ybr[y+j][x+i] = avg
- }
- }
-}
-
-func predFunc8DCLeft(z *Decoder, y, x int) {
- sum := uint32(4)
- for i := 0; i < 8; i++ {
- sum += uint32(z.ybr[y-1][x+i])
- }
- avg := uint8(sum / 8)
- for j := 0; j < 8; j++ {
- for i := 0; i < 8; i++ {
- z.ybr[y+j][x+i] = avg
- }
- }
-}
-
-func predFunc8DCTopLeft(z *Decoder, y, x int) {
- for j := 0; j < 8; j++ {
- for i := 0; i < 8; i++ {
- z.ybr[y+j][x+i] = 0x80
- }
- }
-}
-
-func predFunc16DC(z *Decoder, y, x int) {
- sum := uint32(16)
- for i := 0; i < 16; i++ {
- sum += uint32(z.ybr[y-1][x+i])
- }
- for j := 0; j < 16; j++ {
- sum += uint32(z.ybr[y+j][x-1])
- }
- avg := uint8(sum / 32)
- for j := 0; j < 16; j++ {
- for i := 0; i < 16; i++ {
- z.ybr[y+j][x+i] = avg
- }
- }
-}
-
-func predFunc16TM(z *Decoder, y, x int) {
- delta0 := -int32(z.ybr[y-1][x-1])
- for j := 0; j < 16; j++ {
- delta1 := delta0 + int32(z.ybr[y+j][x-1])
- for i := 0; i < 16; i++ {
- delta2 := delta1 + int32(z.ybr[y-1][x+i])
- z.ybr[y+j][x+i] = uint8(clip(delta2, 0, 255))
- }
- }
-}
-
-func predFunc16VE(z *Decoder, y, x int) {
- for j := 0; j < 16; j++ {
- for i := 0; i < 16; i++ {
- z.ybr[y+j][x+i] = z.ybr[y-1][x+i]
- }
- }
-}
-
-func predFunc16HE(z *Decoder, y, x int) {
- for j := 0; j < 16; j++ {
- for i := 0; i < 16; i++ {
- z.ybr[y+j][x+i] = z.ybr[y+j][x-1]
- }
- }
-}
-
-func predFunc16DCTop(z *Decoder, y, x int) {
- sum := uint32(8)
- for j := 0; j < 16; j++ {
- sum += uint32(z.ybr[y+j][x-1])
- }
- avg := uint8(sum / 16)
- for j := 0; j < 16; j++ {
- for i := 0; i < 16; i++ {
- z.ybr[y+j][x+i] = avg
- }
- }
-}
-
-func predFunc16DCLeft(z *Decoder, y, x int) {
- sum := uint32(8)
- for i := 0; i < 16; i++ {
- sum += uint32(z.ybr[y-1][x+i])
- }
- avg := uint8(sum / 16)
- for j := 0; j < 16; j++ {
- for i := 0; i < 16; i++ {
- z.ybr[y+j][x+i] = avg
- }
- }
-}
-
-func predFunc16DCTopLeft(z *Decoder, y, x int) {
- for j := 0; j < 16; j++ {
- for i := 0; i < 16; i++ {
- z.ybr[y+j][x+i] = 0x80
- }
- }
-}
diff --git a/vendor/golang.org/x/image/vp8/quant.go b/vendor/golang.org/x/image/vp8/quant.go
deleted file mode 100644
index da43616..0000000
--- a/vendor/golang.org/x/image/vp8/quant.go
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package vp8
-
-// This file implements parsing the quantization factors.
-
-// quant are DC/AC quantization factors.
-type quant struct {
- y1 [2]uint16
- y2 [2]uint16
- uv [2]uint16
-}
-
-// clip clips x to the range [min, max] inclusive.
-func clip(x, min, max int32) int32 {
- if x < min {
- return min
- }
- if x > max {
- return max
- }
- return x
-}
-
-// parseQuant parses the quantization factors, as specified in section 9.6.
-func (d *Decoder) parseQuant() {
- baseQ0 := d.fp.readUint(uniformProb, 7)
- dqy1DC := d.fp.readOptionalInt(uniformProb, 4)
- const dqy1AC = 0
- dqy2DC := d.fp.readOptionalInt(uniformProb, 4)
- dqy2AC := d.fp.readOptionalInt(uniformProb, 4)
- dquvDC := d.fp.readOptionalInt(uniformProb, 4)
- dquvAC := d.fp.readOptionalInt(uniformProb, 4)
- for i := 0; i < nSegment; i++ {
- q := int32(baseQ0)
- if d.segmentHeader.useSegment {
- if d.segmentHeader.relativeDelta {
- q += int32(d.segmentHeader.quantizer[i])
- } else {
- q = int32(d.segmentHeader.quantizer[i])
- }
- }
- d.quant[i].y1[0] = dequantTableDC[clip(q+dqy1DC, 0, 127)]
- d.quant[i].y1[1] = dequantTableAC[clip(q+dqy1AC, 0, 127)]
- d.quant[i].y2[0] = dequantTableDC[clip(q+dqy2DC, 0, 127)] * 2
- d.quant[i].y2[1] = dequantTableAC[clip(q+dqy2AC, 0, 127)] * 155 / 100
- if d.quant[i].y2[1] < 8 {
- d.quant[i].y2[1] = 8
- }
- // The 117 is not a typo. The dequant_init function in the spec's Reference
- // Decoder Source Code (http://tools.ietf.org/html/rfc6386#section-9.6 Page 145)
- // says to clamp the LHS value at 132, which is equal to dequantTableDC[117].
- d.quant[i].uv[0] = dequantTableDC[clip(q+dquvDC, 0, 117)]
- d.quant[i].uv[1] = dequantTableAC[clip(q+dquvAC, 0, 127)]
- }
-}
-
-// The dequantization tables are specified in section 14.1.
-var (
- dequantTableDC = [128]uint16{
- 4, 5, 6, 7, 8, 9, 10, 10,
- 11, 12, 13, 14, 15, 16, 17, 17,
- 18, 19, 20, 20, 21, 21, 22, 22,
- 23, 23, 24, 25, 25, 26, 27, 28,
- 29, 30, 31, 32, 33, 34, 35, 36,
- 37, 37, 38, 39, 40, 41, 42, 43,
- 44, 45, 46, 46, 47, 48, 49, 50,
- 51, 52, 53, 54, 55, 56, 57, 58,
- 59, 60, 61, 62, 63, 64, 65, 66,
- 67, 68, 69, 70, 71, 72, 73, 74,
- 75, 76, 76, 77, 78, 79, 80, 81,
- 82, 83, 84, 85, 86, 87, 88, 89,
- 91, 93, 95, 96, 98, 100, 101, 102,
- 104, 106, 108, 110, 112, 114, 116, 118,
- 122, 124, 126, 128, 130, 132, 134, 136,
- 138, 140, 143, 145, 148, 151, 154, 157,
- }
- dequantTableAC = [128]uint16{
- 4, 5, 6, 7, 8, 9, 10, 11,
- 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27,
- 28, 29, 30, 31, 32, 33, 34, 35,
- 36, 37, 38, 39, 40, 41, 42, 43,
- 44, 45, 46, 47, 48, 49, 50, 51,
- 52, 53, 54, 55, 56, 57, 58, 60,
- 62, 64, 66, 68, 70, 72, 74, 76,
- 78, 80, 82, 84, 86, 88, 90, 92,
- 94, 96, 98, 100, 102, 104, 106, 108,
- 110, 112, 114, 116, 119, 122, 125, 128,
- 131, 134, 137, 140, 143, 146, 149, 152,
- 155, 158, 161, 164, 167, 170, 173, 177,
- 181, 185, 189, 193, 197, 201, 205, 209,
- 213, 217, 221, 225, 229, 234, 239, 245,
- 249, 254, 259, 264, 269, 274, 279, 284,
- }
-)
diff --git a/vendor/golang.org/x/image/vp8/reconstruct.go b/vendor/golang.org/x/image/vp8/reconstruct.go
deleted file mode 100644
index c1cc4b5..0000000
--- a/vendor/golang.org/x/image/vp8/reconstruct.go
+++ /dev/null
@@ -1,442 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package vp8
-
-// This file implements decoding DCT/WHT residual coefficients and
-// reconstructing YCbCr data equal to predicted values plus residuals.
-//
-// There are 1*16*16 + 2*8*8 + 1*4*4 coefficients per macroblock:
-// - 1*16*16 luma DCT coefficients,
-// - 2*8*8 chroma DCT coefficients, and
-// - 1*4*4 luma WHT coefficients.
-// Coefficients are read in lots of 16, and the later coefficients in each lot
-// are often zero.
-//
-// The YCbCr data consists of 1*16*16 luma values and 2*8*8 chroma values,
-// plus previously decoded values along the top and left borders. The combined
-// values are laid out as a [1+16+1+8][32]uint8 so that vertically adjacent
-// samples are 32 bytes apart. In detail, the layout is:
-//
-// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
-// . . . . . . . a b b b b b b b b b b b b b b b b c c c c . . . . 0
-// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 1
-// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 2
-// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 3
-// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y c c c c . . . . 4
-// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 5
-// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 6
-// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 7
-// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y c c c c . . . . 8
-// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 9
-// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 10
-// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 11
-// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y c c c c . . . . 12
-// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 13
-// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 14
-// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 15
-// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 16
-// . . . . . . . e f f f f f f f f . . . . . . . g h h h h h h h h 17
-// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 18
-// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 19
-// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 20
-// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 21
-// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 22
-// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 23
-// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 24
-// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 25
-//
-// Y, B and R are the reconstructed luma (Y) and chroma (B, R) values.
-// The Y values are predicted (either as one 16x16 region or 16 4x4 regions)
-// based on the row above's Y values (some combination of {abc} or {dYC}) and
-// the column left's Y values (either {ad} or {bY}). Similarly, B and R values
-// are predicted on the row above and column left of their respective 8x8
-// region: {efi} for B, {ghj} for R.
-//
-// For uppermost macroblocks (i.e. those with mby == 0), the {abcefgh} values
-// are initialized to 0x81. Otherwise, they are copied from the bottom row of
-// the macroblock above. The {c} values are then duplicated from row 0 to rows
-// 4, 8 and 12 of the ybr workspace.
-// Similarly, for leftmost macroblocks (i.e. those with mbx == 0), the {adeigj}
-// values are initialized to 0x7f. Otherwise, they are copied from the right
-// column of the macroblock to the left.
-// For the top-left macroblock (with mby == 0 && mbx == 0), {aeg} is 0x81.
-//
-// When moving from one macroblock to the next horizontally, the {adeigj}
-// values can simply be copied from the workspace to itself, shifted by 8 or
-// 16 columns. When moving from one macroblock to the next vertically,
-// filtering can occur and hence the row values have to be copied from the
-// post-filtered image instead of the pre-filtered workspace.
-
-const (
- bCoeffBase = 1*16*16 + 0*8*8
- rCoeffBase = 1*16*16 + 1*8*8
- whtCoeffBase = 1*16*16 + 2*8*8
-)
-
-const (
- ybrYX = 8
- ybrYY = 1
- ybrBX = 8
- ybrBY = 18
- ybrRX = 24
- ybrRY = 18
-)
-
-// prepareYBR prepares the {abcdefghij} elements of ybr.
-func (d *Decoder) prepareYBR(mbx, mby int) {
- if mbx == 0 {
- for y := 0; y < 17; y++ {
- d.ybr[y][7] = 0x81
- }
- for y := 17; y < 26; y++ {
- d.ybr[y][7] = 0x81
- d.ybr[y][23] = 0x81
- }
- } else {
- for y := 0; y < 17; y++ {
- d.ybr[y][7] = d.ybr[y][7+16]
- }
- for y := 17; y < 26; y++ {
- d.ybr[y][7] = d.ybr[y][15]
- d.ybr[y][23] = d.ybr[y][31]
- }
- }
- if mby == 0 {
- for x := 7; x < 28; x++ {
- d.ybr[0][x] = 0x7f
- }
- for x := 7; x < 16; x++ {
- d.ybr[17][x] = 0x7f
- }
- for x := 23; x < 32; x++ {
- d.ybr[17][x] = 0x7f
- }
- } else {
- for i := 0; i < 16; i++ {
- d.ybr[0][8+i] = d.img.Y[(16*mby-1)*d.img.YStride+16*mbx+i]
- }
- for i := 0; i < 8; i++ {
- d.ybr[17][8+i] = d.img.Cb[(8*mby-1)*d.img.CStride+8*mbx+i]
- }
- for i := 0; i < 8; i++ {
- d.ybr[17][24+i] = d.img.Cr[(8*mby-1)*d.img.CStride+8*mbx+i]
- }
- if mbx == d.mbw-1 {
- for i := 16; i < 20; i++ {
- d.ybr[0][8+i] = d.img.Y[(16*mby-1)*d.img.YStride+16*mbx+15]
- }
- } else {
- for i := 16; i < 20; i++ {
- d.ybr[0][8+i] = d.img.Y[(16*mby-1)*d.img.YStride+16*mbx+i]
- }
- }
- }
- for y := 4; y < 16; y += 4 {
- d.ybr[y][24] = d.ybr[0][24]
- d.ybr[y][25] = d.ybr[0][25]
- d.ybr[y][26] = d.ybr[0][26]
- d.ybr[y][27] = d.ybr[0][27]
- }
-}
-
-// btou converts a bool to a 0/1 value.
-func btou(b bool) uint8 {
- if b {
- return 1
- }
- return 0
-}
-
-// pack packs four 0/1 values into four bits of a uint32.
-func pack(x [4]uint8, shift int) uint32 {
- u := uint32(x[0])<<0 | uint32(x[1])<<1 | uint32(x[2])<<2 | uint32(x[3])<<3
- return u << uint(shift)
-}
-
-// unpack unpacks four 0/1 values from a four-bit value.
-var unpack = [16][4]uint8{
- {0, 0, 0, 0},
- {1, 0, 0, 0},
- {0, 1, 0, 0},
- {1, 1, 0, 0},
- {0, 0, 1, 0},
- {1, 0, 1, 0},
- {0, 1, 1, 0},
- {1, 1, 1, 0},
- {0, 0, 0, 1},
- {1, 0, 0, 1},
- {0, 1, 0, 1},
- {1, 1, 0, 1},
- {0, 0, 1, 1},
- {1, 0, 1, 1},
- {0, 1, 1, 1},
- {1, 1, 1, 1},
-}
-
-var (
- // The mapping from 4x4 region position to band is specified in section 13.3.
- bands = [17]uint8{0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 0}
- // Category probabilties are specified in section 13.2.
- // Decoding categories 1 and 2 are done inline.
- cat3456 = [4][12]uint8{
- {173, 148, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {176, 155, 140, 135, 0, 0, 0, 0, 0, 0, 0, 0},
- {180, 157, 141, 134, 130, 0, 0, 0, 0, 0, 0, 0},
- {254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0},
- }
- // The zigzag order is:
- // 0 1 5 6
- // 2 4 7 12
- // 3 8 11 13
- // 9 10 14 15
- zigzag = [16]uint8{0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15}
-)
-
-// parseResiduals4 parses a 4x4 region of residual coefficients, as specified
-// in section 13.3, and returns a 0/1 value indicating whether there was at
-// least one non-zero coefficient.
-// r is the partition to read bits from.
-// plane and context describe which token probability table to use. context is
-// either 0, 1 or 2, and equals how many of the macroblock left and macroblock
-// above have non-zero coefficients.
-// quant are the DC/AC quantization factors.
-// skipFirstCoeff is whether the DC coefficient has already been parsed.
-// coeffBase is the base index of d.coeff to write to.
-func (d *Decoder) parseResiduals4(r *partition, plane int, context uint8, quant [2]uint16, skipFirstCoeff bool, coeffBase int) uint8 {
- prob, n := &d.tokenProb[plane], 0
- if skipFirstCoeff {
- n = 1
- }
- p := prob[bands[n]][context]
- if !r.readBit(p[0]) {
- return 0
- }
- for n != 16 {
- n++
- if !r.readBit(p[1]) {
- p = prob[bands[n]][0]
- continue
- }
- var v uint32
- if !r.readBit(p[2]) {
- v = 1
- p = prob[bands[n]][1]
- } else {
- if !r.readBit(p[3]) {
- if !r.readBit(p[4]) {
- v = 2
- } else {
- v = 3 + r.readUint(p[5], 1)
- }
- } else if !r.readBit(p[6]) {
- if !r.readBit(p[7]) {
- // Category 1.
- v = 5 + r.readUint(159, 1)
- } else {
- // Category 2.
- v = 7 + 2*r.readUint(165, 1) + r.readUint(145, 1)
- }
- } else {
- // Categories 3, 4, 5 or 6.
- b1 := r.readUint(p[8], 1)
- b0 := r.readUint(p[9+b1], 1)
- cat := 2*b1 + b0
- tab := &cat3456[cat]
- v = 0
- for i := 0; tab[i] != 0; i++ {
- v *= 2
- v += r.readUint(tab[i], 1)
- }
- v += 3 + (8 << cat)
- }
- p = prob[bands[n]][2]
- }
- z := zigzag[n-1]
- c := int32(v) * int32(quant[btou(z > 0)])
- if r.readBit(uniformProb) {
- c = -c
- }
- d.coeff[coeffBase+int(z)] = int16(c)
- if n == 16 || !r.readBit(p[0]) {
- return 1
- }
- }
- return 1
-}
-
-// parseResiduals parses the residuals and returns whether inner loop filtering
-// should be skipped for this macroblock.
-func (d *Decoder) parseResiduals(mbx, mby int) (skip bool) {
- partition := &d.op[mby&(d.nOP-1)]
- plane := planeY1SansY2
- quant := &d.quant[d.segment]
-
- // Parse the DC coefficient of each 4x4 luma region.
- if d.usePredY16 {
- nz := d.parseResiduals4(partition, planeY2, d.leftMB.nzY16+d.upMB[mbx].nzY16, quant.y2, false, whtCoeffBase)
- d.leftMB.nzY16 = nz
- d.upMB[mbx].nzY16 = nz
- d.inverseWHT16()
- plane = planeY1WithY2
- }
-
- var (
- nzDC, nzAC [4]uint8
- nzDCMask, nzACMask uint32
- coeffBase int
- )
-
- // Parse the luma coefficients.
- lnz := unpack[d.leftMB.nzMask&0x0f]
- unz := unpack[d.upMB[mbx].nzMask&0x0f]
- for y := 0; y < 4; y++ {
- nz := lnz[y]
- for x := 0; x < 4; x++ {
- nz = d.parseResiduals4(partition, plane, nz+unz[x], quant.y1, d.usePredY16, coeffBase)
- unz[x] = nz
- nzAC[x] = nz
- nzDC[x] = btou(d.coeff[coeffBase] != 0)
- coeffBase += 16
- }
- lnz[y] = nz
- nzDCMask |= pack(nzDC, y*4)
- nzACMask |= pack(nzAC, y*4)
- }
- lnzMask := pack(lnz, 0)
- unzMask := pack(unz, 0)
-
- // Parse the chroma coefficients.
- lnz = unpack[d.leftMB.nzMask>>4]
- unz = unpack[d.upMB[mbx].nzMask>>4]
- for c := 0; c < 4; c += 2 {
- for y := 0; y < 2; y++ {
- nz := lnz[y+c]
- for x := 0; x < 2; x++ {
- nz = d.parseResiduals4(partition, planeUV, nz+unz[x+c], quant.uv, false, coeffBase)
- unz[x+c] = nz
- nzAC[y*2+x] = nz
- nzDC[y*2+x] = btou(d.coeff[coeffBase] != 0)
- coeffBase += 16
- }
- lnz[y+c] = nz
- }
- nzDCMask |= pack(nzDC, 16+c*2)
- nzACMask |= pack(nzAC, 16+c*2)
- }
- lnzMask |= pack(lnz, 4)
- unzMask |= pack(unz, 4)
-
- // Save decoder state.
- d.leftMB.nzMask = uint8(lnzMask)
- d.upMB[mbx].nzMask = uint8(unzMask)
- d.nzDCMask = nzDCMask
- d.nzACMask = nzACMask
-
- // Section 15.1 of the spec says that "Steps 2 and 4 [of the loop filter]
- // are skipped... [if] there is no DCT coefficient coded for the whole
- // macroblock."
- return nzDCMask == 0 && nzACMask == 0
-}
-
-// reconstructMacroblock applies the predictor functions and adds the inverse-
-// DCT transformed residuals to recover the YCbCr data.
-func (d *Decoder) reconstructMacroblock(mbx, mby int) {
- if d.usePredY16 {
- p := checkTopLeftPred(mbx, mby, d.predY16)
- predFunc16[p](d, 1, 8)
- for j := 0; j < 4; j++ {
- for i := 0; i < 4; i++ {
- n := 4*j + i
- y := 4*j + 1
- x := 4*i + 8
- mask := uint32(1) << uint(n)
- if d.nzACMask&mask != 0 {
- d.inverseDCT4(y, x, 16*n)
- } else if d.nzDCMask&mask != 0 {
- d.inverseDCT4DCOnly(y, x, 16*n)
- }
- }
- }
- } else {
- for j := 0; j < 4; j++ {
- for i := 0; i < 4; i++ {
- n := 4*j + i
- y := 4*j + 1
- x := 4*i + 8
- predFunc4[d.predY4[j][i]](d, y, x)
- mask := uint32(1) << uint(n)
- if d.nzACMask&mask != 0 {
- d.inverseDCT4(y, x, 16*n)
- } else if d.nzDCMask&mask != 0 {
- d.inverseDCT4DCOnly(y, x, 16*n)
- }
- }
- }
- }
- p := checkTopLeftPred(mbx, mby, d.predC8)
- predFunc8[p](d, ybrBY, ybrBX)
- if d.nzACMask&0x0f0000 != 0 {
- d.inverseDCT8(ybrBY, ybrBX, bCoeffBase)
- } else if d.nzDCMask&0x0f0000 != 0 {
- d.inverseDCT8DCOnly(ybrBY, ybrBX, bCoeffBase)
- }
- predFunc8[p](d, ybrRY, ybrRX)
- if d.nzACMask&0xf00000 != 0 {
- d.inverseDCT8(ybrRY, ybrRX, rCoeffBase)
- } else if d.nzDCMask&0xf00000 != 0 {
- d.inverseDCT8DCOnly(ybrRY, ybrRX, rCoeffBase)
- }
-}
-
-// reconstruct reconstructs one macroblock and returns whether inner loop
-// filtering should be skipped for it.
-func (d *Decoder) reconstruct(mbx, mby int) (skip bool) {
- if d.segmentHeader.updateMap {
- if !d.fp.readBit(d.segmentHeader.prob[0]) {
- d.segment = int(d.fp.readUint(d.segmentHeader.prob[1], 1))
- } else {
- d.segment = int(d.fp.readUint(d.segmentHeader.prob[2], 1)) + 2
- }
- }
- if d.useSkipProb {
- skip = d.fp.readBit(d.skipProb)
- }
- // Prepare the workspace.
- for i := range d.coeff {
- d.coeff[i] = 0
- }
- d.prepareYBR(mbx, mby)
- // Parse the predictor modes.
- d.usePredY16 = d.fp.readBit(145)
- if d.usePredY16 {
- d.parsePredModeY16(mbx)
- } else {
- d.parsePredModeY4(mbx)
- }
- d.parsePredModeC8()
- // Parse the residuals.
- if !skip {
- skip = d.parseResiduals(mbx, mby)
- } else {
- if d.usePredY16 {
- d.leftMB.nzY16 = 0
- d.upMB[mbx].nzY16 = 0
- }
- d.leftMB.nzMask = 0
- d.upMB[mbx].nzMask = 0
- d.nzDCMask = 0
- d.nzACMask = 0
- }
- // Reconstruct the YCbCr data and copy it to the image.
- d.reconstructMacroblock(mbx, mby)
- for i, y := (mby*d.img.YStride+mbx)*16, 0; y < 16; i, y = i+d.img.YStride, y+1 {
- copy(d.img.Y[i:i+16], d.ybr[ybrYY+y][ybrYX:ybrYX+16])
- }
- for i, y := (mby*d.img.CStride+mbx)*8, 0; y < 8; i, y = i+d.img.CStride, y+1 {
- copy(d.img.Cb[i:i+8], d.ybr[ybrBY+y][ybrBX:ybrBX+8])
- copy(d.img.Cr[i:i+8], d.ybr[ybrRY+y][ybrRX:ybrRX+8])
- }
- return skip
-}
diff --git a/vendor/golang.org/x/image/vp8/token.go b/vendor/golang.org/x/image/vp8/token.go
deleted file mode 100644
index da99cf0..0000000
--- a/vendor/golang.org/x/image/vp8/token.go
+++ /dev/null
@@ -1,381 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package vp8
-
-// This file contains token probabilities for decoding DCT/WHT coefficients, as
-// specified in chapter 13.
-
-func (d *Decoder) parseTokenProb() {
- for i := range d.tokenProb {
- for j := range d.tokenProb[i] {
- for k := range d.tokenProb[i][j] {
- for l := range d.tokenProb[i][j][k] {
- if d.fp.readBit(tokenProbUpdateProb[i][j][k][l]) {
- d.tokenProb[i][j][k][l] = uint8(d.fp.readUint(uniformProb, 8))
- }
- }
- }
- }
- }
-}
-
-// The plane enumeration is specified in section 13.3.
-const (
- planeY1WithY2 = iota
- planeY2
- planeUV
- planeY1SansY2
- nPlane
-)
-
-const (
- nBand = 8
- nContext = 3
- nProb = 11
-)
-
-// Token probability update probabilities are specified in section 13.4.
-var tokenProbUpdateProb = [nPlane][nBand][nContext][nProb]uint8{
- {
- {
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- },
- {
- {176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255},
- {249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255},
- },
- {
- {255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255},
- {234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
- {253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- },
- {
- {255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255},
- {239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
- {254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
- },
- {
- {255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255},
- {251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- },
- {
- {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
- {251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
- {254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
- },
- {
- {255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255},
- {250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255},
- {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- },
- {
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- },
- },
- {
- {
- {217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255},
- {234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255},
- },
- {
- {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
- {238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255},
- },
- {
- {255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255},
- {249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- },
- {
- {255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- },
- {
- {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
- {252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- },
- {
- {255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
- {253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- },
- {
- {255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255},
- {250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- },
- {
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- },
- },
- {
- {
- {186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255},
- {234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255},
- {251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255},
- },
- {
- {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
- {236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
- {251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255},
- },
- {
- {255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
- {254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- },
- {
- {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- },
- {
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- },
- {
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- },
- {
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- },
- {
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- },
- },
- {
- {
- {248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255},
- {248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255},
- },
- {
- {255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255},
- {246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255},
- {252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255},
- },
- {
- {255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255},
- {248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255},
- {253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255},
- },
- {
- {255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255},
- {245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255},
- {253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
- },
- {
- {255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255},
- {252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
- {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- },
- {
- {255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
- {255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
- },
- {
- {255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255},
- {250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- },
- {
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
- },
- },
-}
-
-// Default token probabilities are specified in section 13.5.
-var defaultTokenProb = [nPlane][nBand][nContext][nProb]uint8{
- {
- {
- {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
- {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
- {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
- },
- {
- {253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128},
- {189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128},
- {106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128},
- },
- {
- {1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128},
- {181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128},
- {78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128},
- },
- {
- {1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128},
- {184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128},
- {77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128},
- },
- {
- {1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128},
- {170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128},
- {37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128},
- },
- {
- {1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128},
- {207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128},
- {102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128},
- },
- {
- {1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128},
- {177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128},
- {80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128},
- },
- {
- {1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
- {246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
- {255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
- },
- },
- {
- {
- {198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62},
- {131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1},
- {68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128},
- },
- {
- {1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128},
- {184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128},
- {81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128},
- },
- {
- {1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128},
- {99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128},
- {23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128},
- },
- {
- {1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128},
- {109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128},
- {44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128},
- },
- {
- {1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128},
- {94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128},
- {22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128},
- },
- {
- {1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128},
- {124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128},
- {35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128},
- },
- {
- {1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128},
- {121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128},
- {45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128},
- },
- {
- {1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128},
- {203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128},
- {137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128},
- },
- },
- {
- {
- {253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128},
- {175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128},
- {73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128},
- },
- {
- {1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128},
- {239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128},
- {155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128},
- },
- {
- {1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128},
- {201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128},
- {69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128},
- },
- {
- {1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128},
- {223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128},
- {141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128},
- },
- {
- {1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128},
- {190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128},
- {149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
- },
- {
- {1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128},
- {247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128},
- {240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128},
- },
- {
- {1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128},
- {213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128},
- {55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128},
- },
- {
- {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
- {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
- {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
- },
- },
- {
- {
- {202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255},
- {126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128},
- {61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128},
- },
- {
- {1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128},
- {166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128},
- {39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128},
- },
- {
- {1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128},
- {124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128},
- {24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128},
- },
- {
- {1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128},
- {149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128},
- {28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128},
- },
- {
- {1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128},
- {123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128},
- {20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128},
- },
- {
- {1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128},
- {168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128},
- {47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128},
- },
- {
- {1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128},
- {141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128},
- {42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128},
- },
- {
- {1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
- {244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
- {238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
- },
- },
-}
diff --git a/vendor/golang.org/x/image/vp8l/decode.go b/vendor/golang.org/x/image/vp8l/decode.go
deleted file mode 100644
index 4319487..0000000
--- a/vendor/golang.org/x/image/vp8l/decode.go
+++ /dev/null
@@ -1,603 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package vp8l implements a decoder for the VP8L lossless image format.
-//
-// The VP8L specification is at:
-// https://developers.google.com/speed/webp/docs/riff_container
-package vp8l // import "golang.org/x/image/vp8l"
-
-import (
- "bufio"
- "errors"
- "image"
- "image/color"
- "io"
-)
-
-var (
- errInvalidCodeLengths = errors.New("vp8l: invalid code lengths")
- errInvalidHuffmanTree = errors.New("vp8l: invalid Huffman tree")
-)
-
-// colorCacheMultiplier is the multiplier used for the color cache hash
-// function, specified in section 4.2.3.
-const colorCacheMultiplier = 0x1e35a7bd
-
-// distanceMapTable is the look-up table for distanceMap.
-var distanceMapTable = [120]uint8{
- 0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a,
- 0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a,
- 0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b,
- 0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03,
- 0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c,
- 0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e,
- 0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b,
- 0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f,
- 0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b,
- 0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41,
- 0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f,
- 0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70,
-}
-
-// distanceMap maps a LZ77 backwards reference distance to a two-dimensional
-// pixel offset, specified in section 4.2.2.
-func distanceMap(w int32, code uint32) int32 {
- if int32(code) > int32(len(distanceMapTable)) {
- return int32(code) - int32(len(distanceMapTable))
- }
- distCode := int32(distanceMapTable[code-1])
- yOffset := distCode >> 4
- xOffset := 8 - distCode&0xf
- if d := yOffset*w + xOffset; d >= 1 {
- return d
- }
- return 1
-}
-
-// decoder holds the bit-stream for a VP8L image.
-type decoder struct {
- r io.ByteReader
- bits uint32
- nBits uint32
-}
-
-// read reads the next n bits from the decoder's bit-stream.
-func (d *decoder) read(n uint32) (uint32, error) {
- for d.nBits < n {
- c, err := d.r.ReadByte()
- if err != nil {
- if err == io.EOF {
- err = io.ErrUnexpectedEOF
- }
- return 0, err
- }
- d.bits |= uint32(c) << d.nBits
- d.nBits += 8
- }
- u := d.bits & (1<>= n
- d.nBits -= n
- return u, nil
-}
-
-// decodeTransform decodes the next transform and the width of the image after
-// transformation (or equivalently, before inverse transformation), specified
-// in section 3.
-func (d *decoder) decodeTransform(w int32, h int32) (t transform, newWidth int32, err error) {
- t.oldWidth = w
- t.transformType, err = d.read(2)
- if err != nil {
- return transform{}, 0, err
- }
- switch t.transformType {
- case transformTypePredictor, transformTypeCrossColor:
- t.bits, err = d.read(3)
- if err != nil {
- return transform{}, 0, err
- }
- t.bits += 2
- t.pix, err = d.decodePix(nTiles(w, t.bits), nTiles(h, t.bits), 0, false)
- if err != nil {
- return transform{}, 0, err
- }
- case transformTypeSubtractGreen:
- // No-op.
- case transformTypeColorIndexing:
- nColors, err := d.read(8)
- if err != nil {
- return transform{}, 0, err
- }
- nColors++
- t.bits = 0
- switch {
- case nColors <= 2:
- t.bits = 3
- case nColors <= 4:
- t.bits = 2
- case nColors <= 16:
- t.bits = 1
- }
- w = nTiles(w, t.bits)
- pix, err := d.decodePix(int32(nColors), 1, 4*256, false)
- if err != nil {
- return transform{}, 0, err
- }
- for p := 4; p < len(pix); p += 4 {
- pix[p+0] += pix[p-4]
- pix[p+1] += pix[p-3]
- pix[p+2] += pix[p-2]
- pix[p+3] += pix[p-1]
- }
- // The spec says that "if the index is equal or larger than color_table_size,
- // the argb color value should be set to 0x00000000 (transparent black)."
- // We re-slice up to 256 4-byte pixels.
- t.pix = pix[:4*256]
- }
- return t, w, nil
-}
-
-// repeatsCodeLength is the minimum code length for repeated codes.
-const repeatsCodeLength = 16
-
-// These magic numbers are specified at the end of section 5.2.2.
-// The 3-length arrays apply to code lengths >= repeatsCodeLength.
-var (
- codeLengthCodeOrder = [19]uint8{
- 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- }
- repeatBits = [3]uint8{2, 3, 7}
- repeatOffsets = [3]uint8{3, 3, 11}
-)
-
-// decodeCodeLengths decodes a Huffman tree's code lengths which are themselves
-// encoded via a Huffman tree, specified in section 5.2.2.
-func (d *decoder) decodeCodeLengths(dst []uint32, codeLengthCodeLengths []uint32) error {
- h := hTree{}
- if err := h.build(codeLengthCodeLengths); err != nil {
- return err
- }
-
- maxSymbol := len(dst)
- useLength, err := d.read(1)
- if err != nil {
- return err
- }
- if useLength != 0 {
- n, err := d.read(3)
- if err != nil {
- return err
- }
- n = 2 + 2*n
- ms, err := d.read(n)
- if err != nil {
- return err
- }
- maxSymbol = int(ms) + 2
- if maxSymbol > len(dst) {
- return errInvalidCodeLengths
- }
- }
-
- // The spec says that "if code 16 [meaning repeat] is used before
- // a non-zero value has been emitted, a value of 8 is repeated."
- prevCodeLength := uint32(8)
-
- for symbol := 0; symbol < len(dst); {
- if maxSymbol == 0 {
- break
- }
- maxSymbol--
- codeLength, err := h.next(d)
- if err != nil {
- return err
- }
- if codeLength < repeatsCodeLength {
- dst[symbol] = codeLength
- symbol++
- if codeLength != 0 {
- prevCodeLength = codeLength
- }
- continue
- }
-
- repeat, err := d.read(uint32(repeatBits[codeLength-repeatsCodeLength]))
- if err != nil {
- return err
- }
- repeat += uint32(repeatOffsets[codeLength-repeatsCodeLength])
- if symbol+int(repeat) > len(dst) {
- return errInvalidCodeLengths
- }
- // A code length of 16 repeats the previous non-zero code.
- // A code length of 17 or 18 repeats zeroes.
- cl := uint32(0)
- if codeLength == 16 {
- cl = prevCodeLength
- }
- for ; repeat > 0; repeat-- {
- dst[symbol] = cl
- symbol++
- }
- }
- return nil
-}
-
-// decodeHuffmanTree decodes a Huffman tree into h.
-func (d *decoder) decodeHuffmanTree(h *hTree, alphabetSize uint32) error {
- useSimple, err := d.read(1)
- if err != nil {
- return err
- }
- if useSimple != 0 {
- nSymbols, err := d.read(1)
- if err != nil {
- return err
- }
- nSymbols++
- firstSymbolLengthCode, err := d.read(1)
- if err != nil {
- return err
- }
- firstSymbolLengthCode = 7*firstSymbolLengthCode + 1
- var symbols [2]uint32
- symbols[0], err = d.read(firstSymbolLengthCode)
- if err != nil {
- return err
- }
- if nSymbols == 2 {
- symbols[1], err = d.read(8)
- if err != nil {
- return err
- }
- }
- return h.buildSimple(nSymbols, symbols, alphabetSize)
- }
-
- nCodes, err := d.read(4)
- if err != nil {
- return err
- }
- nCodes += 4
- if int(nCodes) > len(codeLengthCodeOrder) {
- return errInvalidHuffmanTree
- }
- codeLengthCodeLengths := [len(codeLengthCodeOrder)]uint32{}
- for i := uint32(0); i < nCodes; i++ {
- codeLengthCodeLengths[codeLengthCodeOrder[i]], err = d.read(3)
- if err != nil {
- return err
- }
- }
- codeLengths := make([]uint32, alphabetSize)
- if err = d.decodeCodeLengths(codeLengths, codeLengthCodeLengths[:]); err != nil {
- return err
- }
- return h.build(codeLengths)
-}
-
-const (
- huffGreen = 0
- huffRed = 1
- huffBlue = 2
- huffAlpha = 3
- huffDistance = 4
- nHuff = 5
-)
-
-// hGroup is an array of 5 Huffman trees.
-type hGroup [nHuff]hTree
-
-// decodeHuffmanGroups decodes the one or more hGroups used to decode the pixel
-// data. If one hGroup is used for the entire image, then hPix and hBits will
-// be zero. If more than one hGroup is used, then hPix contains the meta-image
-// that maps tiles to hGroup index, and hBits contains the log-2 tile size.
-func (d *decoder) decodeHuffmanGroups(w int32, h int32, topLevel bool, ccBits uint32) (
- hGroups []hGroup, hPix []byte, hBits uint32, err error) {
-
- maxHGroupIndex := 0
- if topLevel {
- useMeta, err := d.read(1)
- if err != nil {
- return nil, nil, 0, err
- }
- if useMeta != 0 {
- hBits, err = d.read(3)
- if err != nil {
- return nil, nil, 0, err
- }
- hBits += 2
- hPix, err = d.decodePix(nTiles(w, hBits), nTiles(h, hBits), 0, false)
- if err != nil {
- return nil, nil, 0, err
- }
- for p := 0; p < len(hPix); p += 4 {
- i := int(hPix[p])<<8 | int(hPix[p+1])
- if maxHGroupIndex < i {
- maxHGroupIndex = i
- }
- }
- }
- }
- hGroups = make([]hGroup, maxHGroupIndex+1)
- for i := range hGroups {
- for j, alphabetSize := range alphabetSizes {
- if j == 0 && ccBits > 0 {
- alphabetSize += 1 << ccBits
- }
- if err := d.decodeHuffmanTree(&hGroups[i][j], alphabetSize); err != nil {
- return nil, nil, 0, err
- }
- }
- }
- return hGroups, hPix, hBits, nil
-}
-
-const (
- nLiteralCodes = 256
- nLengthCodes = 24
- nDistanceCodes = 40
-)
-
-var alphabetSizes = [nHuff]uint32{
- nLiteralCodes + nLengthCodes,
- nLiteralCodes,
- nLiteralCodes,
- nLiteralCodes,
- nDistanceCodes,
-}
-
-// decodePix decodes pixel data, specified in section 5.2.2.
-func (d *decoder) decodePix(w int32, h int32, minCap int32, topLevel bool) ([]byte, error) {
- // Decode the color cache parameters.
- ccBits, ccShift, ccEntries := uint32(0), uint32(0), ([]uint32)(nil)
- useColorCache, err := d.read(1)
- if err != nil {
- return nil, err
- }
- if useColorCache != 0 {
- ccBits, err = d.read(4)
- if err != nil {
- return nil, err
- }
- if ccBits < 1 || 11 < ccBits {
- return nil, errors.New("vp8l: invalid color cache parameters")
- }
- ccShift = 32 - ccBits
- ccEntries = make([]uint32, 1<>hBits) + (x >> hBits))
- hg = &hGroups[uint32(hPix[i])<<8|uint32(hPix[i+1])]
- }
-
- green, err := hg[huffGreen].next(d)
- if err != nil {
- return nil, err
- }
- switch {
- case green < nLiteralCodes:
- // We have a literal pixel.
- red, err := hg[huffRed].next(d)
- if err != nil {
- return nil, err
- }
- blue, err := hg[huffBlue].next(d)
- if err != nil {
- return nil, err
- }
- alpha, err := hg[huffAlpha].next(d)
- if err != nil {
- return nil, err
- }
- pix[p+0] = uint8(red)
- pix[p+1] = uint8(green)
- pix[p+2] = uint8(blue)
- pix[p+3] = uint8(alpha)
- p += 4
-
- x++
- if x == w {
- x, y = 0, y+1
- }
- lookupHG = hMask != 0 && x&hMask == 0
-
- case green < nLiteralCodes+nLengthCodes:
- // We have a LZ77 backwards reference.
- length, err := d.lz77Param(green - nLiteralCodes)
- if err != nil {
- return nil, err
- }
- distSym, err := hg[huffDistance].next(d)
- if err != nil {
- return nil, err
- }
- distCode, err := d.lz77Param(distSym)
- if err != nil {
- return nil, err
- }
- dist := distanceMap(w, distCode)
- pEnd := p + 4*int(length)
- q := p - 4*int(dist)
- qEnd := pEnd - 4*int(dist)
- if p < 0 || len(pix) < pEnd || q < 0 || len(pix) < qEnd {
- return nil, errors.New("vp8l: invalid LZ77 parameters")
- }
- for ; p < pEnd; p, q = p+1, q+1 {
- pix[p] = pix[q]
- }
-
- x += int32(length)
- for x >= w {
- x, y = x-w, y+1
- }
- lookupHG = hMask != 0
-
- default:
- // We have a color cache lookup. First, insert previous pixels
- // into the cache. Note that VP8L assumes ARGB order, but the
- // Go image.RGBA type is in RGBA order.
- for ; cachedP < p; cachedP += 4 {
- argb := uint32(pix[cachedP+0])<<16 |
- uint32(pix[cachedP+1])<<8 |
- uint32(pix[cachedP+2])<<0 |
- uint32(pix[cachedP+3])<<24
- ccEntries[(argb*colorCacheMultiplier)>>ccShift] = argb
- }
- green -= nLiteralCodes + nLengthCodes
- if int(green) >= len(ccEntries) {
- return nil, errors.New("vp8l: invalid color cache index")
- }
- argb := ccEntries[green]
- pix[p+0] = uint8(argb >> 16)
- pix[p+1] = uint8(argb >> 8)
- pix[p+2] = uint8(argb >> 0)
- pix[p+3] = uint8(argb >> 24)
- p += 4
-
- x++
- if x == w {
- x, y = 0, y+1
- }
- lookupHG = hMask != 0 && x&hMask == 0
- }
- }
- return pix, nil
-}
-
-// lz77Param returns the next LZ77 parameter: a length or a distance, specified
-// in section 4.2.2.
-func (d *decoder) lz77Param(symbol uint32) (uint32, error) {
- if symbol < 4 {
- return symbol + 1, nil
- }
- extraBits := (symbol - 2) >> 1
- offset := (2 + symbol&1) << extraBits
- n, err := d.read(extraBits)
- if err != nil {
- return 0, err
- }
- return offset + n + 1, nil
-}
-
-// decodeHeader decodes the VP8L header from r.
-func decodeHeader(r io.Reader) (d *decoder, w int32, h int32, err error) {
- rr, ok := r.(io.ByteReader)
- if !ok {
- rr = bufio.NewReader(r)
- }
- d = &decoder{r: rr}
- magic, err := d.read(8)
- if err != nil {
- return nil, 0, 0, err
- }
- if magic != 0x2f {
- return nil, 0, 0, errors.New("vp8l: invalid header")
- }
- width, err := d.read(14)
- if err != nil {
- return nil, 0, 0, err
- }
- width++
- height, err := d.read(14)
- if err != nil {
- return nil, 0, 0, err
- }
- height++
- _, err = d.read(1) // Read and ignore the hasAlpha hint.
- if err != nil {
- return nil, 0, 0, err
- }
- version, err := d.read(3)
- if err != nil {
- return nil, 0, 0, err
- }
- if version != 0 {
- return nil, 0, 0, errors.New("vp8l: invalid version")
- }
- return d, int32(width), int32(height), nil
-}
-
-// DecodeConfig decodes the color model and dimensions of a VP8L image from r.
-func DecodeConfig(r io.Reader) (image.Config, error) {
- _, w, h, err := decodeHeader(r)
- if err != nil {
- return image.Config{}, err
- }
- return image.Config{
- ColorModel: color.NRGBAModel,
- Width: int(w),
- Height: int(h),
- }, nil
-}
-
-// Decode decodes a VP8L image from r.
-func Decode(r io.Reader) (image.Image, error) {
- d, w, h, err := decodeHeader(r)
- if err != nil {
- return nil, err
- }
- // Decode the transforms.
- var (
- nTransforms int
- transforms [nTransformTypes]transform
- transformsSeen [nTransformTypes]bool
- originalW = w
- )
- for {
- more, err := d.read(1)
- if err != nil {
- return nil, err
- }
- if more == 0 {
- break
- }
- var t transform
- t, w, err = d.decodeTransform(w, h)
- if err != nil {
- return nil, err
- }
- if transformsSeen[t.transformType] {
- return nil, errors.New("vp8l: repeated transform")
- }
- transformsSeen[t.transformType] = true
- transforms[nTransforms] = t
- nTransforms++
- }
- // Decode the transformed pixels.
- pix, err := d.decodePix(w, h, 0, true)
- if err != nil {
- return nil, err
- }
- // Apply the inverse transformations.
- for i := nTransforms - 1; i >= 0; i-- {
- t := &transforms[i]
- pix = inverseTransforms[t.transformType](t, pix, h)
- }
- return &image.NRGBA{
- Pix: pix,
- Stride: 4 * int(originalW),
- Rect: image.Rect(0, 0, int(originalW), int(h)),
- }, nil
-}
diff --git a/vendor/golang.org/x/image/vp8l/huffman.go b/vendor/golang.org/x/image/vp8l/huffman.go
deleted file mode 100644
index 36368a8..0000000
--- a/vendor/golang.org/x/image/vp8l/huffman.go
+++ /dev/null
@@ -1,245 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package vp8l
-
-import (
- "io"
-)
-
-// reverseBits reverses the bits in a byte.
-var reverseBits = [256]uint8{
- 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
- 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
- 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
- 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
- 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
- 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
- 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
- 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
- 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
- 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
- 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
- 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
- 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
- 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
- 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
- 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
-}
-
-// hNode is a node in a Huffman tree.
-type hNode struct {
- // symbol is the symbol held by this node.
- symbol uint32
- // children, if positive, is the hTree.nodes index of the first of
- // this node's two children. Zero means an uninitialized node,
- // and -1 means a leaf node.
- children int32
-}
-
-const leafNode = -1
-
-// lutSize is the log-2 size of an hTree's look-up table.
-const lutSize, lutMask = 7, 1<<7 - 1
-
-// hTree is a Huffman tree.
-type hTree struct {
- // nodes are the nodes of the Huffman tree. During construction,
- // len(nodes) grows from 1 up to cap(nodes) by steps of two.
- // After construction, len(nodes) == cap(nodes), and both equal
- // 2*theNumberOfSymbols - 1.
- nodes []hNode
- // lut is a look-up table for walking the nodes. The x in lut[x] is
- // the next lutSize bits in the bit-stream. The low 8 bits of lut[x]
- // equals 1 plus the number of bits in the next code, or 0 if the
- // next code requires more than lutSize bits. The high 24 bits are:
- // - the symbol, if the code requires lutSize or fewer bits, or
- // - the hTree.nodes index to start the tree traversal from, if
- // the next code requires more than lutSize bits.
- lut [1 << lutSize]uint32
-}
-
-// insert inserts into the hTree a symbol whose encoding is the least
-// significant codeLength bits of code.
-func (h *hTree) insert(symbol uint32, code uint32, codeLength uint32) error {
- if symbol > 0xffff || codeLength > 0xfe {
- return errInvalidHuffmanTree
- }
- baseCode := uint32(0)
- if codeLength > lutSize {
- baseCode = uint32(reverseBits[(code>>(codeLength-lutSize))&0xff]) >> (8 - lutSize)
- } else {
- baseCode = uint32(reverseBits[code&0xff]) >> (8 - codeLength)
- for i := 0; i < 1<<(lutSize-codeLength); i++ {
- h.lut[baseCode|uint32(i)< 0; {
- codeLength--
- if int(n) > len(h.nodes) {
- return errInvalidHuffmanTree
- }
- switch h.nodes[n].children {
- case leafNode:
- return errInvalidHuffmanTree
- case 0:
- if len(h.nodes) == cap(h.nodes) {
- return errInvalidHuffmanTree
- }
- // Create two empty child nodes.
- h.nodes[n].children = int32(len(h.nodes))
- h.nodes = h.nodes[:len(h.nodes)+2]
- }
- n = uint32(h.nodes[n].children) + 1&(code>>codeLength)
- jump--
- if jump == 0 && h.lut[baseCode] == 0 {
- h.lut[baseCode] = n << 8
- }
- }
-
- switch h.nodes[n].children {
- case leafNode:
- // No-op.
- case 0:
- // Turn the uninitialized node into a leaf.
- h.nodes[n].children = leafNode
- default:
- return errInvalidHuffmanTree
- }
- h.nodes[n].symbol = symbol
- return nil
-}
-
-// codeLengthsToCodes returns the canonical Huffman codes implied by the
-// sequence of code lengths.
-func codeLengthsToCodes(codeLengths []uint32) ([]uint32, error) {
- maxCodeLength := uint32(0)
- for _, cl := range codeLengths {
- if maxCodeLength < cl {
- maxCodeLength = cl
- }
- }
- const maxAllowedCodeLength = 15
- if len(codeLengths) == 0 || maxCodeLength > maxAllowedCodeLength {
- return nil, errInvalidHuffmanTree
- }
- histogram := [maxAllowedCodeLength + 1]uint32{}
- for _, cl := range codeLengths {
- histogram[cl]++
- }
- currCode, nextCodes := uint32(0), [maxAllowedCodeLength + 1]uint32{}
- for cl := 1; cl < len(nextCodes); cl++ {
- currCode = (currCode + histogram[cl-1]) << 1
- nextCodes[cl] = currCode
- }
- codes := make([]uint32, len(codeLengths))
- for symbol, cl := range codeLengths {
- if cl > 0 {
- codes[symbol] = nextCodes[cl]
- nextCodes[cl]++
- }
- }
- return codes, nil
-}
-
-// build builds a canonical Huffman tree from the given code lengths.
-func (h *hTree) build(codeLengths []uint32) error {
- // Calculate the number of symbols.
- var nSymbols, lastSymbol uint32
- for symbol, cl := range codeLengths {
- if cl != 0 {
- nSymbols++
- lastSymbol = uint32(symbol)
- }
- }
- if nSymbols == 0 {
- return errInvalidHuffmanTree
- }
- h.nodes = make([]hNode, 1, 2*nSymbols-1)
- // Handle the trivial case.
- if nSymbols == 1 {
- if len(codeLengths) <= int(lastSymbol) {
- return errInvalidHuffmanTree
- }
- return h.insert(lastSymbol, 0, 0)
- }
- // Handle the non-trivial case.
- codes, err := codeLengthsToCodes(codeLengths)
- if err != nil {
- return err
- }
- for symbol, cl := range codeLengths {
- if cl > 0 {
- if err := h.insert(uint32(symbol), codes[symbol], cl); err != nil {
- return err
- }
- }
- }
- return nil
-}
-
-// buildSimple builds a Huffman tree with 1 or 2 symbols.
-func (h *hTree) buildSimple(nSymbols uint32, symbols [2]uint32, alphabetSize uint32) error {
- h.nodes = make([]hNode, 1, 2*nSymbols-1)
- for i := uint32(0); i < nSymbols; i++ {
- if symbols[i] >= alphabetSize {
- return errInvalidHuffmanTree
- }
- if err := h.insert(symbols[i], i, nSymbols-1); err != nil {
- return err
- }
- }
- return nil
-}
-
-// next returns the next Huffman-encoded symbol from the bit-stream d.
-func (h *hTree) next(d *decoder) (uint32, error) {
- var n uint32
- // Read enough bits so that we can use the look-up table.
- if d.nBits < lutSize {
- c, err := d.r.ReadByte()
- if err != nil {
- if err == io.EOF {
- // There are no more bytes of data, but we may still be able
- // to read the next symbol out of the previously read bits.
- goto slowPath
- }
- return 0, err
- }
- d.bits |= uint32(c) << d.nBits
- d.nBits += 8
- }
- // Use the look-up table.
- n = h.lut[d.bits&lutMask]
- if b := n & 0xff; b != 0 {
- b--
- d.bits >>= b
- d.nBits -= b
- return n >> 8, nil
- }
- n >>= 8
- d.bits >>= lutSize
- d.nBits -= lutSize
-
-slowPath:
- for h.nodes[n].children != leafNode {
- if d.nBits == 0 {
- c, err := d.r.ReadByte()
- if err != nil {
- if err == io.EOF {
- err = io.ErrUnexpectedEOF
- }
- return 0, err
- }
- d.bits = uint32(c)
- d.nBits = 8
- }
- n = uint32(h.nodes[n].children) + 1&d.bits
- d.bits >>= 1
- d.nBits--
- }
- return h.nodes[n].symbol, nil
-}
diff --git a/vendor/golang.org/x/image/vp8l/transform.go b/vendor/golang.org/x/image/vp8l/transform.go
deleted file mode 100644
index 06543da..0000000
--- a/vendor/golang.org/x/image/vp8l/transform.go
+++ /dev/null
@@ -1,299 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package vp8l
-
-// This file deals with image transforms, specified in section 3.
-
-// nTiles returns the number of tiles needed to cover size pixels, where each
-// tile's side is 1<> bits
-}
-
-const (
- transformTypePredictor = 0
- transformTypeCrossColor = 1
- transformTypeSubtractGreen = 2
- transformTypeColorIndexing = 3
- nTransformTypes = 4
-)
-
-// transform holds the parameters for an invertible transform.
-type transform struct {
- // transformType is the type of the transform.
- transformType uint32
- // oldWidth is the width of the image before transformation (or
- // equivalently, after inverse transformation). The color-indexing
- // transform can reduce the width. For example, a 50-pixel-wide
- // image that only needs 4 bits (half a byte) per color index can
- // be transformed into a 25-pixel-wide image.
- oldWidth int32
- // bits is the log-2 size of the transform's tiles, for the predictor
- // and cross-color transforms. 8>>bits is the number of bits per
- // color index, for the color-index transform.
- bits uint32
- // pix is the tile values, for the predictor and cross-color
- // transforms, and the color palette, for the color-index transform.
- pix []byte
-}
-
-var inverseTransforms = [nTransformTypes]func(*transform, []byte, int32) []byte{
- transformTypePredictor: inversePredictor,
- transformTypeCrossColor: inverseCrossColor,
- transformTypeSubtractGreen: inverseSubtractGreen,
- transformTypeColorIndexing: inverseColorIndexing,
-}
-
-func inversePredictor(t *transform, pix []byte, h int32) []byte {
- if t.oldWidth == 0 || h == 0 {
- return pix
- }
- // The first pixel's predictor is mode 0 (opaque black).
- pix[3] += 0xff
- p, mask := int32(4), int32(1)<> t.bits) * tilesPerRow
- predictorMode := t.pix[q+1] & 0x0f
- q += 4
- for x := int32(1); x < t.oldWidth; x++ {
- if x&mask == 0 {
- predictorMode = t.pix[q+1] & 0x0f
- q += 4
- }
- switch predictorMode {
- case 0: // Opaque black.
- pix[p+3] += 0xff
-
- case 1: // L.
- pix[p+0] += pix[p-4]
- pix[p+1] += pix[p-3]
- pix[p+2] += pix[p-2]
- pix[p+3] += pix[p-1]
-
- case 2: // T.
- pix[p+0] += pix[top+0]
- pix[p+1] += pix[top+1]
- pix[p+2] += pix[top+2]
- pix[p+3] += pix[top+3]
-
- case 3: // TR.
- pix[p+0] += pix[top+4]
- pix[p+1] += pix[top+5]
- pix[p+2] += pix[top+6]
- pix[p+3] += pix[top+7]
-
- case 4: // TL.
- pix[p+0] += pix[top-4]
- pix[p+1] += pix[top-3]
- pix[p+2] += pix[top-2]
- pix[p+3] += pix[top-1]
-
- case 5: // Average2(Average2(L, TR), T).
- pix[p+0] += avg2(avg2(pix[p-4], pix[top+4]), pix[top+0])
- pix[p+1] += avg2(avg2(pix[p-3], pix[top+5]), pix[top+1])
- pix[p+2] += avg2(avg2(pix[p-2], pix[top+6]), pix[top+2])
- pix[p+3] += avg2(avg2(pix[p-1], pix[top+7]), pix[top+3])
-
- case 6: // Average2(L, TL).
- pix[p+0] += avg2(pix[p-4], pix[top-4])
- pix[p+1] += avg2(pix[p-3], pix[top-3])
- pix[p+2] += avg2(pix[p-2], pix[top-2])
- pix[p+3] += avg2(pix[p-1], pix[top-1])
-
- case 7: // Average2(L, T).
- pix[p+0] += avg2(pix[p-4], pix[top+0])
- pix[p+1] += avg2(pix[p-3], pix[top+1])
- pix[p+2] += avg2(pix[p-2], pix[top+2])
- pix[p+3] += avg2(pix[p-1], pix[top+3])
-
- case 8: // Average2(TL, T).
- pix[p+0] += avg2(pix[top-4], pix[top+0])
- pix[p+1] += avg2(pix[top-3], pix[top+1])
- pix[p+2] += avg2(pix[top-2], pix[top+2])
- pix[p+3] += avg2(pix[top-1], pix[top+3])
-
- case 9: // Average2(T, TR).
- pix[p+0] += avg2(pix[top+0], pix[top+4])
- pix[p+1] += avg2(pix[top+1], pix[top+5])
- pix[p+2] += avg2(pix[top+2], pix[top+6])
- pix[p+3] += avg2(pix[top+3], pix[top+7])
-
- case 10: // Average2(Average2(L, TL), Average2(T, TR)).
- pix[p+0] += avg2(avg2(pix[p-4], pix[top-4]), avg2(pix[top+0], pix[top+4]))
- pix[p+1] += avg2(avg2(pix[p-3], pix[top-3]), avg2(pix[top+1], pix[top+5]))
- pix[p+2] += avg2(avg2(pix[p-2], pix[top-2]), avg2(pix[top+2], pix[top+6]))
- pix[p+3] += avg2(avg2(pix[p-1], pix[top-1]), avg2(pix[top+3], pix[top+7]))
-
- case 11: // Select(L, T, TL).
- l0 := int32(pix[p-4])
- l1 := int32(pix[p-3])
- l2 := int32(pix[p-2])
- l3 := int32(pix[p-1])
- c0 := int32(pix[top-4])
- c1 := int32(pix[top-3])
- c2 := int32(pix[top-2])
- c3 := int32(pix[top-1])
- t0 := int32(pix[top+0])
- t1 := int32(pix[top+1])
- t2 := int32(pix[top+2])
- t3 := int32(pix[top+3])
- l := abs(c0-t0) + abs(c1-t1) + abs(c2-t2) + abs(c3-t3)
- t := abs(c0-l0) + abs(c1-l1) + abs(c2-l2) + abs(c3-l3)
- if l < t {
- pix[p+0] += uint8(l0)
- pix[p+1] += uint8(l1)
- pix[p+2] += uint8(l2)
- pix[p+3] += uint8(l3)
- } else {
- pix[p+0] += uint8(t0)
- pix[p+1] += uint8(t1)
- pix[p+2] += uint8(t2)
- pix[p+3] += uint8(t3)
- }
-
- case 12: // ClampAddSubtractFull(L, T, TL).
- pix[p+0] += clampAddSubtractFull(pix[p-4], pix[top+0], pix[top-4])
- pix[p+1] += clampAddSubtractFull(pix[p-3], pix[top+1], pix[top-3])
- pix[p+2] += clampAddSubtractFull(pix[p-2], pix[top+2], pix[top-2])
- pix[p+3] += clampAddSubtractFull(pix[p-1], pix[top+3], pix[top-1])
-
- case 13: // ClampAddSubtractHalf(Average2(L, T), TL).
- pix[p+0] += clampAddSubtractHalf(avg2(pix[p-4], pix[top+0]), pix[top-4])
- pix[p+1] += clampAddSubtractHalf(avg2(pix[p-3], pix[top+1]), pix[top-3])
- pix[p+2] += clampAddSubtractHalf(avg2(pix[p-2], pix[top+2]), pix[top-2])
- pix[p+3] += clampAddSubtractHalf(avg2(pix[p-1], pix[top+3]), pix[top-1])
- }
- p, top = p+4, top+4
- }
- }
- return pix
-}
-
-func inverseCrossColor(t *transform, pix []byte, h int32) []byte {
- var greenToRed, greenToBlue, redToBlue int32
- p, mask, tilesPerRow := int32(0), int32(1)<> t.bits) * tilesPerRow
- for x := int32(0); x < t.oldWidth; x++ {
- if x&mask == 0 {
- redToBlue = int32(int8(t.pix[q+0]))
- greenToBlue = int32(int8(t.pix[q+1]))
- greenToRed = int32(int8(t.pix[q+2]))
- q += 4
- }
- red := pix[p+0]
- green := pix[p+1]
- blue := pix[p+2]
- red += uint8(uint32(greenToRed*int32(int8(green))) >> 5)
- blue += uint8(uint32(greenToBlue*int32(int8(green))) >> 5)
- blue += uint8(uint32(redToBlue*int32(int8(red))) >> 5)
- pix[p+0] = red
- pix[p+2] = blue
- p += 4
- }
- }
- return pix
-}
-
-func inverseSubtractGreen(t *transform, pix []byte, h int32) []byte {
- for p := 0; p < len(pix); p += 4 {
- green := pix[p+1]
- pix[p+0] += green
- pix[p+2] += green
- }
- return pix
-}
-
-func inverseColorIndexing(t *transform, pix []byte, h int32) []byte {
- if t.bits == 0 {
- for p := 0; p < len(pix); p += 4 {
- i := 4 * uint32(pix[p+1])
- pix[p+0] = t.pix[i+0]
- pix[p+1] = t.pix[i+1]
- pix[p+2] = t.pix[i+2]
- pix[p+3] = t.pix[i+3]
- }
- return pix
- }
-
- vMask, xMask, bitsPerPixel := uint32(0), int32(0), uint32(8>>t.bits)
- switch t.bits {
- case 1:
- vMask, xMask = 0x0f, 0x01
- case 2:
- vMask, xMask = 0x03, 0x03
- case 3:
- vMask, xMask = 0x01, 0x07
- }
-
- d, p, v, dst := 0, 0, uint32(0), make([]byte, 4*t.oldWidth*h)
- for y := int32(0); y < h; y++ {
- for x := int32(0); x < t.oldWidth; x++ {
- if x&xMask == 0 {
- v = uint32(pix[p+1])
- p += 4
- }
-
- i := 4 * (v & vMask)
- dst[d+0] = t.pix[i+0]
- dst[d+1] = t.pix[i+1]
- dst[d+2] = t.pix[i+2]
- dst[d+3] = t.pix[i+3]
- d += 4
-
- v >>= bitsPerPixel
- }
- }
- return dst
-}
-
-func abs(x int32) int32 {
- if x < 0 {
- return -x
- }
- return x
-}
-
-func avg2(a, b uint8) uint8 {
- return uint8((int32(a) + int32(b)) / 2)
-}
-
-func clampAddSubtractFull(a, b, c uint8) uint8 {
- x := int32(a) + int32(b) - int32(c)
- if x < 0 {
- return 0
- }
- if x > 255 {
- return 255
- }
- return uint8(x)
-}
-
-func clampAddSubtractHalf(a, b uint8) uint8 {
- x := int32(a) + (int32(a)-int32(b))/2
- if x < 0 {
- return 0
- }
- if x > 255 {
- return 255
- }
- return uint8(x)
-}
diff --git a/vendor/golang.org/x/image/webp/decode.go b/vendor/golang.org/x/image/webp/decode.go
deleted file mode 100644
index 111f358..0000000
--- a/vendor/golang.org/x/image/webp/decode.go
+++ /dev/null
@@ -1,272 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build go1.6
-
-package webp
-
-import (
- "bytes"
- "errors"
- "image"
- "image/color"
- "io"
-
- "golang.org/x/image/riff"
- "golang.org/x/image/vp8"
- "golang.org/x/image/vp8l"
-)
-
-var errInvalidFormat = errors.New("webp: invalid format")
-
-var (
- fccALPH = riff.FourCC{'A', 'L', 'P', 'H'}
- fccVP8 = riff.FourCC{'V', 'P', '8', ' '}
- fccVP8L = riff.FourCC{'V', 'P', '8', 'L'}
- fccVP8X = riff.FourCC{'V', 'P', '8', 'X'}
- fccWEBP = riff.FourCC{'W', 'E', 'B', 'P'}
-)
-
-func decode(r io.Reader, configOnly bool) (image.Image, image.Config, error) {
- formType, riffReader, err := riff.NewReader(r)
- if err != nil {
- return nil, image.Config{}, err
- }
- if formType != fccWEBP {
- return nil, image.Config{}, errInvalidFormat
- }
-
- var (
- alpha []byte
- alphaStride int
- wantAlpha bool
- widthMinusOne uint32
- heightMinusOne uint32
- buf [10]byte
- )
- for {
- chunkID, chunkLen, chunkData, err := riffReader.Next()
- if err == io.EOF {
- err = errInvalidFormat
- }
- if err != nil {
- return nil, image.Config{}, err
- }
-
- switch chunkID {
- case fccALPH:
- if !wantAlpha {
- return nil, image.Config{}, errInvalidFormat
- }
- wantAlpha = false
- // Read the Pre-processing | Filter | Compression byte.
- if _, err := io.ReadFull(chunkData, buf[:1]); err != nil {
- if err == io.EOF {
- err = errInvalidFormat
- }
- return nil, image.Config{}, err
- }
- alpha, alphaStride, err = readAlpha(chunkData, widthMinusOne, heightMinusOne, buf[0]&0x03)
- if err != nil {
- return nil, image.Config{}, err
- }
- unfilterAlpha(alpha, alphaStride, (buf[0]>>2)&0x03)
-
- case fccVP8:
- if wantAlpha || int32(chunkLen) < 0 {
- return nil, image.Config{}, errInvalidFormat
- }
- d := vp8.NewDecoder()
- d.Init(chunkData, int(chunkLen))
- fh, err := d.DecodeFrameHeader()
- if err != nil {
- return nil, image.Config{}, err
- }
- if configOnly {
- return nil, image.Config{
- ColorModel: color.YCbCrModel,
- Width: fh.Width,
- Height: fh.Height,
- }, nil
- }
- m, err := d.DecodeFrame()
- if err != nil {
- return nil, image.Config{}, err
- }
- if alpha != nil {
- return &image.NYCbCrA{
- YCbCr: *m,
- A: alpha,
- AStride: alphaStride,
- }, image.Config{}, nil
- }
- return m, image.Config{}, nil
-
- case fccVP8L:
- if wantAlpha || alpha != nil {
- return nil, image.Config{}, errInvalidFormat
- }
- if configOnly {
- c, err := vp8l.DecodeConfig(chunkData)
- return nil, c, err
- }
- m, err := vp8l.Decode(chunkData)
- return m, image.Config{}, err
-
- case fccVP8X:
- if chunkLen != 10 {
- return nil, image.Config{}, errInvalidFormat
- }
- if _, err := io.ReadFull(chunkData, buf[:10]); err != nil {
- return nil, image.Config{}, err
- }
- const (
- animationBit = 1 << 1
- xmpMetadataBit = 1 << 2
- exifMetadataBit = 1 << 3
- alphaBit = 1 << 4
- iccProfileBit = 1 << 5
- )
- if buf[0] != alphaBit {
- return nil, image.Config{}, errors.New("webp: non-Alpha VP8X is not implemented")
- }
- widthMinusOne = uint32(buf[4]) | uint32(buf[5])<<8 | uint32(buf[6])<<16
- heightMinusOne = uint32(buf[7]) | uint32(buf[8])<<8 | uint32(buf[9])<<16
- if configOnly {
- return nil, image.Config{
- ColorModel: color.NYCbCrAModel,
- Width: int(widthMinusOne) + 1,
- Height: int(heightMinusOne) + 1,
- }, nil
- }
- wantAlpha = true
-
- default:
- return nil, image.Config{}, errInvalidFormat
- }
- }
-}
-
-func readAlpha(chunkData io.Reader, widthMinusOne, heightMinusOne uint32, compression byte) (
- alpha []byte, alphaStride int, err error) {
-
- switch compression {
- case 0:
- w := int(widthMinusOne) + 1
- h := int(heightMinusOne) + 1
- alpha = make([]byte, w*h)
- if _, err := io.ReadFull(chunkData, alpha); err != nil {
- return nil, 0, err
- }
- return alpha, w, nil
-
- case 1:
- // Read the VP8L-compressed alpha values. First, synthesize a 5-byte VP8L header:
- // a 1-byte magic number, a 14-bit widthMinusOne, a 14-bit heightMinusOne,
- // a 1-bit (ignored, zero) alphaIsUsed and a 3-bit (zero) version.
- // TODO(nigeltao): be more efficient than decoding an *image.NRGBA just to
- // extract the green values to a separately allocated []byte. Fixing this
- // will require changes to the vp8l package's API.
- if widthMinusOne > 0x3fff || heightMinusOne > 0x3fff {
- return nil, 0, errors.New("webp: invalid format")
- }
- alphaImage, err := vp8l.Decode(io.MultiReader(
- bytes.NewReader([]byte{
- 0x2f, // VP8L magic number.
- uint8(widthMinusOne),
- uint8(widthMinusOne>>8) | uint8(heightMinusOne<<6),
- uint8(heightMinusOne >> 2),
- uint8(heightMinusOne >> 10),
- }),
- chunkData,
- ))
- if err != nil {
- return nil, 0, err
- }
- // The green values of the inner NRGBA image are the alpha values of the
- // outer NYCbCrA image.
- pix := alphaImage.(*image.NRGBA).Pix
- alpha = make([]byte, len(pix)/4)
- for i := range alpha {
- alpha[i] = pix[4*i+1]
- }
- return alpha, int(widthMinusOne) + 1, nil
- }
- return nil, 0, errInvalidFormat
-}
-
-func unfilterAlpha(alpha []byte, alphaStride int, filter byte) {
- if len(alpha) == 0 || alphaStride == 0 {
- return
- }
- switch filter {
- case 1: // Horizontal filter.
- for i := 1; i < alphaStride; i++ {
- alpha[i] += alpha[i-1]
- }
- for i := alphaStride; i < len(alpha); i += alphaStride {
- // The first column is equivalent to the vertical filter.
- alpha[i] += alpha[i-alphaStride]
-
- for j := 1; j < alphaStride; j++ {
- alpha[i+j] += alpha[i+j-1]
- }
- }
-
- case 2: // Vertical filter.
- // The first row is equivalent to the horizontal filter.
- for i := 1; i < alphaStride; i++ {
- alpha[i] += alpha[i-1]
- }
-
- for i := alphaStride; i < len(alpha); i++ {
- alpha[i] += alpha[i-alphaStride]
- }
-
- case 3: // Gradient filter.
- // The first row is equivalent to the horizontal filter.
- for i := 1; i < alphaStride; i++ {
- alpha[i] += alpha[i-1]
- }
-
- for i := alphaStride; i < len(alpha); i += alphaStride {
- // The first column is equivalent to the vertical filter.
- alpha[i] += alpha[i-alphaStride]
-
- // The interior is predicted on the three top/left pixels.
- for j := 1; j < alphaStride; j++ {
- c := int(alpha[i+j-alphaStride-1])
- b := int(alpha[i+j-alphaStride])
- a := int(alpha[i+j-1])
- x := a + b - c
- if x < 0 {
- x = 0
- } else if x > 255 {
- x = 255
- }
- alpha[i+j] += uint8(x)
- }
- }
- }
-}
-
-// Decode reads a WEBP image from r and returns it as an image.Image.
-func Decode(r io.Reader) (image.Image, error) {
- m, _, err := decode(r, false)
- if err != nil {
- return nil, err
- }
- return m, err
-}
-
-// DecodeConfig returns the color model and dimensions of a WEBP image without
-// decoding the entire image.
-func DecodeConfig(r io.Reader) (image.Config, error) {
- _, c, err := decode(r, true)
- return c, err
-}
-
-func init() {
- image.RegisterFormat("webp", "RIFF????WEBPVP8", Decode, DecodeConfig)
-}
diff --git a/vendor/golang.org/x/image/webp/webp.go b/vendor/golang.org/x/image/webp/webp.go
deleted file mode 100644
index 850cdc8..0000000
--- a/vendor/golang.org/x/image/webp/webp.go
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2016 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package webp implements a decoder for WEBP images.
-//
-// WEBP is defined at:
-// https://developers.google.com/speed/webp/docs/riff_container
-//
-// It requires Go 1.6 or later.
-package webp // import "golang.org/x/image/webp"
-
-// This blank Go file, other than the package clause, exists so that this
-// package can be built for Go 1.5 and earlier. (The other files in this
-// package are all marked "+build go1.6" for the NYCbCrA types introduced in Go
-// 1.6). There is no functionality in a blank package, but some image
-// manipulation programs might still underscore import this package for the
-// side effect of registering the WEBP format with the standard library's
-// image.RegisterFormat and image.Decode functions. For example, that program
-// might contain:
-//
-// // Underscore imports to register some formats for image.Decode.
-// import _ "image/gif"
-// import _ "image/jpeg"
-// import _ "image/png"
-// import _ "golang.org/x/image/webp"
-//
-// Such a program will still compile for Go 1.5 (due to this placeholder Go
-// file). It will simply not be able to recognize and decode WEBP (but still
-// handle GIF, JPEG and PNG).
diff --git a/vendor/modules.txt b/vendor/modules.txt
deleted file mode 100644
index 39a3970..0000000
--- a/vendor/modules.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-# code.ivysaur.me/imagequant v2.12.2-go1.2+incompatible
-code.ivysaur.me/imagequant
-# github.com/hashicorp/golang-lru v0.5.0
-github.com/hashicorp/golang-lru
-github.com/hashicorp/golang-lru/simplelru
-# golang.org/x/image v0.0.0-20180601115456-af66defab954
-golang.org/x/image/bmp
-golang.org/x/image/draw
-golang.org/x/image/webp
-golang.org/x/image/math/f64
-golang.org/x/image/riff
-golang.org/x/image/vp8
-golang.org/x/image/vp8l