/app/app.go
https://code.google.com/p/go-thanksgiving/ · Go · 372 lines · 119 code · 23 blank · 230 comment · 19 complexity · 3bfde52e113b6da4608077565d3a2539 MD5 · raw file
- /*
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
- 1. Definitions.
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor 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, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
- END OF TERMS AND CONDITIONS
- APPENDIX: How to apply the Apache License to your work.
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
- Copyright 2011 Google Inc.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- package app
- import (
- "appengine"
- "fmt"
- "http"
- "image"
- "image/draw"
- "image/jpeg"
- "image/png"
- "os"
- "path/filepath"
- "strings"
- "sync"
- )
- const (
- backgroundImageFile = "img/bg/thanksgiving-2011-actual-size-bg-nolinks.png"
- defaultImageFile = "img/00000000.png"
- prefix = "/thumb/"
- )
- var (
- // dirs maps each layout element to its location on disk.
- dirs = map[string]string{
- "h": "img/heads",
- "b": "img/eyes_beak",
- "i": "img/index_feathers",
- "m": "img/middle_feathers",
- "r": "img/ring_feathers",
- "p": "img/pinky_feathers",
- "f": "img/feet",
- "w": "img/wing",
- }
- // urlMap maps each URL character position to
- // its corresponding layout element.
- urlMap = [...]string{"b", "h", "i", "m", "r", "p", "f", "w"}
- // layoutMap maps each layout element to its position
- // on the background image.
- layoutMap = map[string]image.Rectangle{
- "h": {image.Pt(109, 50), image.Pt(166, 152)},
- "i": {image.Pt(136, 21), image.Pt(180, 131)},
- "m": {image.Pt(159, 7), image.Pt(201, 126)},
- "r": {image.Pt(188, 20), image.Pt(230, 125)},
- "p": {image.Pt(216, 48), image.Pt(258, 134)},
- "f": {image.Pt(155, 176), image.Pt(243, 213)},
- "w": {image.Pt(169, 118), image.Pt(250, 197)},
- "b": {image.Pt(105, 104), image.Pt(145, 148)},
- }
- // elements maps each layout element to its images.
- elements = make(map[string][]*image.RGBA)
- // backgroundImage contains the background image data.
- backgroundImage *image.RGBA
- // defaultImage is the image that is served if an error occurs.
- defaultImage *image.RGBA
- // imageQuality is the encoding quality setting for the output image.
- imageQuality = jpeg.Options{95}
- )
- func init() {
- http.HandleFunc(prefix, handler)
- }
- // handler serves a turkey snapshot for the given request.
- func handler(w http.ResponseWriter, r *http.Request) {
- // Defer a function to recover from any panics.
- // When recovering from a panic, log the error condition to
- // the App Engine dashboard and send the default image to the user.
- defer func() {
- if err := recover(); err != nil {
- c := appengine.NewContext(r)
- c.Errorf("%s", err)
- c.Errorf("%s", "Traceback: "+r.RawURL)
- if defaultImage != nil {
- w.Header().Set("Content-type", "image/jpeg")
- jpeg.Encode(w, defaultImage, &imageQuality)
- }
- }
- }()
- // Load images from disk on the first request.
- loadOnce.Do(load)
- // Make a copy of the background to draw into.
- bgRect := backgroundImage.Bounds()
- m := image.NewRGBA(bgRect.Dx(), bgRect.Dy())
- draw.Draw(m, m.Bounds(), backgroundImage, image.ZP, draw.Over)
- // Process each character of the request string.
- code := strings.ToLower(r.URL.Path[len(prefix):])
- for i, p := range code {
- // Decode hex character p in place.
- if p < 'a' {
- // it's a digit
- p = p - '0'
- } else {
- // it's a letter
- p = p - 'a' + 10
- }
- t := urlMap[i] // element type by index
- em := elements[t] // element images by type
- if p >= len(em) {
- panic(fmt.Sprintf("element index out of range %s: "+
- "%d >= %d", t, p, len(em)))
- }
- // Draw the element to m,
- // using the layoutMap to specify its position.
- draw.Draw(m, layoutMap[t], em[p], image.ZP, draw.Over)
- }
- // Encode JPEG image and write it as the response.
- w.Header().Set("Content-type", "image/jpeg")
- w.Header().Set("cache-control", "public, max-age=259200")
- jpeg.Encode(w, m, &imageQuality)
- }
- // loadOnce is used to call the load function only on the first request.
- var loadOnce sync.Once
- // load reads the various PNG images from disk and stores them in their
- // corresponding global variables.
- func load() {
- defaultImage = loadPNG(defaultImageFile)
- backgroundImage = loadPNG(backgroundImageFile)
- for dirKey, dir := range dirs {
- paths, err := filepath.Glob(dir + "/*.png")
- if err != nil {
- panic(err)
- }
- for _, p := range paths {
- elements[dirKey] = append(elements[dirKey], loadPNG(p))
- }
- }
- }
- // loadPNG loads a PNG image from disk and returns it as an *image.RGBA.
- func loadPNG(filename string) *image.RGBA {
- f, err := os.Open(filename)
- if err != nil {
- panic(err)
- }
- defer f.Close()
- m, err := png.Decode(f)
- if err != nil {
- panic(err)
- }
- return rgba(m)
- }
- // rgba converts an image.Image to an *image.RGBA.
- func rgba(m image.Image) *image.RGBA {
- if r, ok := m.(*image.RGBA); ok {
- return r
- }
- b := m.Bounds()
- r := image.NewRGBA(b.Dx(), b.Dy())
- draw.Draw(r, b, m, image.ZP, draw.Src)
- return r
- }