doubleVision 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +100 -0
- data/Rakefile +2 -0
- data/bin/doubleVision +54 -0
- data/doubleVision.gemspec +21 -0
- data/examples/Day.png +0 -0
- data/examples/DayNight.png +0 -0
- data/examples/Night.png +0 -0
- data/examples/test1.png +0 -0
- data/examples/test2.png +0 -0
- data/examples/testout.png +0 -0
- data/lib/doubleVision.rb +79 -0
- data/lib/doubleVision/version.rb +3 -0
- metadata +78 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Tristan Hume
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
# DoubleVision
|
2
|
+
|
3
|
+
I recently was shown trick by a friend where an image was posted on a website
|
4
|
+
that displayed one thing in the thumbnail and another in the lightbox.
|
5
|
+
http://funnyjunk.com/channel/ponytime/rainbow+dash/llhuDyy/15#15
|
6
|
+
|
7
|
+
I set out to create a program that generates these images and this is what I came up with.
|
8
|
+
|
9
|
+
The output images look like this:
|
10
|
+
|
11
|
+

|
12
|
+
|
13
|
+
Try downloading it to your computer and then viewing it. Cool eh?
|
14
|
+
|
15
|
+
## How it works
|
16
|
+
The PNG specification contains a metadata attribute that allows you to specify the gamma to render the image with. The thing is, not all renderers support this.
|
17
|
+
|
18
|
+
If an image is created with normal pixels spaced out around a grid of very light-colored pixels.
|
19
|
+
The light colored pixels are actually the pixels of the second image reverse-mapped through a gamma function.
|
20
|
+
However, they are so light they look white.
|
21
|
+
|
22
|
+
When the image is displayed with a very low gamma (I use 0.023).
|
23
|
+
The normal pixels become almost black and the light pixels become the colors of the second image.
|
24
|
+
|
25
|
+
Example:
|
26
|
+

|
27
|
+
|
28
|
+
## Why?
|
29
|
+
By taking of advantage of this, we can create png files that display a different picture if the renderer supports the gamma attribute.
|
30
|
+
|
31
|
+
Things that do not support the gamma attribute:
|
32
|
+
|
33
|
+
- Thumbnail renderers (Facebook, etc...)
|
34
|
+
- Apple png rendering
|
35
|
+
- Windows png rendering
|
36
|
+
|
37
|
+
Things that **do** support the gamma attribute:
|
38
|
+
|
39
|
+
- Firefox (uses libpng wich supports the attribute)
|
40
|
+
- Google Chrome
|
41
|
+
|
42
|
+
This can lead to interesting combos.
|
43
|
+
For example:
|
44
|
+
|
45
|
+
- linking the image on facebook can show one image as a thumbnail but a completely different one when the link is clicked.
|
46
|
+
- A picture that detects the user's browser. (Chrome/Firefox or Safari)
|
47
|
+
- A picture that displays one thing in the browser and a different thing when downloaded to the user's (victim's) computer.
|
48
|
+
|
49
|
+
## Installation
|
50
|
+
|
51
|
+
Add this line to your application's Gemfile:
|
52
|
+
|
53
|
+
gem 'doubleVision'
|
54
|
+
|
55
|
+
And then execute:
|
56
|
+
|
57
|
+
$ bundle
|
58
|
+
|
59
|
+
Or install it yourself as:
|
60
|
+
|
61
|
+
$ gem install doubleVision
|
62
|
+
|
63
|
+
## Usage
|
64
|
+
|
65
|
+
Next, run the program like this:
|
66
|
+
|
67
|
+
doubleVision withgamma.png withoutgamma.png out.png
|
68
|
+
|
69
|
+
obviously replacing the filenames with your own.
|
70
|
+
|
71
|
+
It will combine the images into one image (out.png) that will display
|
72
|
+
withgamma.png when viewed with gamma support (e.g. in Firefox)
|
73
|
+
and withoutgamma.png when displayed without gamma support (e.g. As a thumbnail)
|
74
|
+
|
75
|
+
## Other Example
|
76
|
+
|
77
|
+

|
78
|
+
|
79
|
+
Was generated from:
|
80
|
+

|
81
|
+
and
|
82
|
+

|
83
|
+
|
84
|
+
##FAQ
|
85
|
+
|
86
|
+
- Why are the images so dark? -
|
87
|
+
The images have to be darkened so that they do not show up in the other image.
|
88
|
+
One image is also full of black pixels which make it look dark.
|
89
|
+
- Are you a wizard?
|
90
|
+
Sadly, no. But programmers are almost the same thing.
|
91
|
+
|
92
|
+
*Disclaimer: Frequently Asked Questions are not necessarily frequently asked, nor are they always questions.*
|
93
|
+
|
94
|
+
## Contributing
|
95
|
+
|
96
|
+
1. Fork it
|
97
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
98
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
99
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
100
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/bin/doubleVision
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "doubleVision"
|
4
|
+
|
5
|
+
require 'optparse'
|
6
|
+
|
7
|
+
options = { :gamma => 0.023, :fade1 => 220/255.0, :fade2 => 210/255.0, :shift => 10}
|
8
|
+
USAGE = "Usage: doubleVision [options] withgamma.png withoutgamma.png out.png"
|
9
|
+
|
10
|
+
optParser = OptionParser.new do |opts|
|
11
|
+
opts.banner = USAGE
|
12
|
+
|
13
|
+
opts.separator " "
|
14
|
+
|
15
|
+
opts.on("-g", "--gamma gamma", Float,
|
16
|
+
"Specify the gamma value to use.",
|
17
|
+
"Default: #{options[:gamma]}"
|
18
|
+
) { |v| options[:gamma] = v}
|
19
|
+
|
20
|
+
opts.on("-f","--gammafade fract", Float,
|
21
|
+
"Specify the factor used to lower the brightness of the first image.",
|
22
|
+
"Needed for images with full white pixels that show up in the non-gamma image.",
|
23
|
+
"Default: #{options[:fade1]}"
|
24
|
+
) { |v| options[:fade1] = v}
|
25
|
+
opts.on("-F","--nogammafade fract", Float,
|
26
|
+
"Specify the factor used to lower the brightness of the second image.",
|
27
|
+
"Needed for images with bright pixels that show up in the gamma image.",
|
28
|
+
"Default: #{options[:fade2]}"
|
29
|
+
) { |v| options[:fade2] = v}
|
30
|
+
|
31
|
+
opts.on("-s","--shift fract", Float,
|
32
|
+
"Specify the amount to shift up brightness in the first image.",
|
33
|
+
"Needed for images with full black pixels that show up in the non-gamma image.",
|
34
|
+
"Default: #{options[:shift]}"
|
35
|
+
) { |v| options[:shift] = v}
|
36
|
+
|
37
|
+
opts.separator ""
|
38
|
+
|
39
|
+
opts.on("-h", "--help", "Show this help message.") { puts opts; exit }
|
40
|
+
end
|
41
|
+
optParser.parse!
|
42
|
+
|
43
|
+
outfile = ARGV[2]
|
44
|
+
|
45
|
+
puts "Generating image..."
|
46
|
+
unless ARGV.length < 3
|
47
|
+
DoubleVision.createImageFiles(ARGV[0],ARGV[1],outfile,options)
|
48
|
+
else
|
49
|
+
puts "Must provide images to use."
|
50
|
+
puts optParser
|
51
|
+
exit
|
52
|
+
end
|
53
|
+
|
54
|
+
puts "Sucessfully created #{outfile}"
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/doubleVision/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Tristan Hume"]
|
6
|
+
gem.email = ["tris.hume@gmail.com"]
|
7
|
+
gem.description = %q{Allows you to create magic PNG images that display differently in the browser than in thumbnails.}
|
8
|
+
gem.summary = %q{Generates magic thumbnail images.}
|
9
|
+
gem.homepage = "https://github.com/trishume/doubleVision"
|
10
|
+
|
11
|
+
gem.add_runtime_dependency 'chunky_png'
|
12
|
+
gem.post_install_message = "Installed! Now run the 'doubleVision' command to try it out."
|
13
|
+
gem.bindir = "bin"
|
14
|
+
gem.executables << 'doubleVision'
|
15
|
+
|
16
|
+
gem.files = `git ls-files`.split($\)
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.name = "doubleVision"
|
19
|
+
gem.require_paths = ["lib"]
|
20
|
+
gem.version = DoubleVision::VERSION
|
21
|
+
end
|
data/examples/Day.png
ADDED
Binary file
|
Binary file
|
data/examples/Night.png
ADDED
Binary file
|
data/examples/test1.png
ADDED
Binary file
|
data/examples/test2.png
ADDED
Binary file
|
Binary file
|
data/lib/doubleVision.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
require "doubleVision/version"
|
2
|
+
|
3
|
+
require "chunky_png"
|
4
|
+
|
5
|
+
# Manipulates PNG gamma metadata to create images that
|
6
|
+
# display differently when rendered in different clients.
|
7
|
+
#
|
8
|
+
# Can be used to create images that display differently as
|
9
|
+
# thumbnails than when they are clicked on sites like facebook.
|
10
|
+
module DoubleVision
|
11
|
+
# turns a color component from 0-255 into a new color for the firefox image
|
12
|
+
def DoubleVision.trans(num,options)
|
13
|
+
scaled = num*options[:fade1] + options[:shift]
|
14
|
+
(((scaled/255.0)**(options[:gamma]))*255.0).floor
|
15
|
+
end
|
16
|
+
|
17
|
+
# Takes to ChunkyPNG::Image and returns the chunkypng datastream
|
18
|
+
# of an image that displays img1 when rendered with gamma support
|
19
|
+
# and img2 without it.
|
20
|
+
#
|
21
|
+
# Will throw an ArgumentError if the images do not have the same dimensions.
|
22
|
+
#
|
23
|
+
# Options is a hash containing various parameters
|
24
|
+
# [:gamma] is the gamma value to use. This should be a very low value.
|
25
|
+
# [:fade1] is the amount to fade the first image. Default is 220/255.0
|
26
|
+
# [:fade2] is the amount to fade the second image. Default is 210/255.0
|
27
|
+
# [:shift] is the amount to shift up the colours of the second image. Default is 10.
|
28
|
+
# The fade and shift parameters are required to properly segment the colors so the algorithm works.
|
29
|
+
def DoubleVision.createImage(img1,img2,options = {})
|
30
|
+
options[:gamma] ||= 0.023
|
31
|
+
options[:fade1] ||= 220/255.0
|
32
|
+
options[:fade2] ||= 210/255.0
|
33
|
+
options[:shift] ||= 10
|
34
|
+
|
35
|
+
if img1.dimension != img2.dimension
|
36
|
+
raise ArgumentError, "Image sizes must have the same dimensions."
|
37
|
+
end
|
38
|
+
|
39
|
+
out = ChunkyPNG::Image.new(img1.dimension.width*2, img1.dimension.height*2,ChunkyPNG::Color::BLACK)
|
40
|
+
|
41
|
+
out.dimension.width.times do |x|
|
42
|
+
out.dimension.height.times do |y|
|
43
|
+
if x % 2 == 0 && y % 2 == 0
|
44
|
+
col = img1[x/2,y/2]
|
45
|
+
r = trans(ChunkyPNG::Color.r(col),options)
|
46
|
+
g = trans(ChunkyPNG::Color.g(col),options)
|
47
|
+
b = trans(ChunkyPNG::Color.b(col),options)
|
48
|
+
out[x,y] = ChunkyPNG::Color.rgb(r,g,b)
|
49
|
+
else
|
50
|
+
col = img2[x/2,y/2]
|
51
|
+
r = (ChunkyPNG::Color.r(col) * options[:fade2]).round
|
52
|
+
g = (ChunkyPNG::Color.g(col) * options[:fade2]).round
|
53
|
+
b = (ChunkyPNG::Color.b(col) * options[:fade2]).round
|
54
|
+
out[x,y] = ChunkyPNG::Color.rgb(r,g,b)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
pngGamma = (options[:gamma]*100000).to_i
|
60
|
+
# turn the integer into a 4 byte big-endian unsigned int byte string
|
61
|
+
bytestr = [pngGamma].pack("L>")
|
62
|
+
# The chunk is named gAMA because the PNG spec is weird
|
63
|
+
chunk = ChunkyPNG::Chunk::Generic.new("gAMA",bytestr)
|
64
|
+
ds = out.to_datastream
|
65
|
+
ds.other_chunks << chunk
|
66
|
+
ds
|
67
|
+
end
|
68
|
+
|
69
|
+
# Creates a magic image from two png files of the same size.
|
70
|
+
# Takes two filenames and saves the result in outFile.
|
71
|
+
#
|
72
|
+
# Will throw an ArgumentError if the images do not have the same dimensions.
|
73
|
+
def DoubleVision.createImageFiles(file1,file2,outFile,options = {})
|
74
|
+
img1 = ChunkyPNG::Image.from_file(file1)
|
75
|
+
img2 = ChunkyPNG::Image.from_file(file2)
|
76
|
+
out = createImage(img1,img2,options)
|
77
|
+
out.save(outFile)
|
78
|
+
end
|
79
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: doubleVision
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Tristan Hume
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-04-27 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: chunky_png
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
description: Allows you to create magic PNG images that display differently in the
|
31
|
+
browser than in thumbnails.
|
32
|
+
email:
|
33
|
+
- tris.hume@gmail.com
|
34
|
+
executables:
|
35
|
+
- doubleVision
|
36
|
+
extensions: []
|
37
|
+
extra_rdoc_files: []
|
38
|
+
files:
|
39
|
+
- .gitignore
|
40
|
+
- Gemfile
|
41
|
+
- LICENSE
|
42
|
+
- README.md
|
43
|
+
- Rakefile
|
44
|
+
- bin/doubleVision
|
45
|
+
- doubleVision.gemspec
|
46
|
+
- examples/Day.png
|
47
|
+
- examples/DayNight.png
|
48
|
+
- examples/Night.png
|
49
|
+
- examples/test1.png
|
50
|
+
- examples/test2.png
|
51
|
+
- examples/testout.png
|
52
|
+
- lib/doubleVision.rb
|
53
|
+
- lib/doubleVision/version.rb
|
54
|
+
homepage: https://github.com/trishume/doubleVision
|
55
|
+
licenses: []
|
56
|
+
post_install_message: Installed! Now run the 'doubleVision' command to try it out.
|
57
|
+
rdoc_options: []
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ! '>='
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
requirements: []
|
73
|
+
rubyforge_project:
|
74
|
+
rubygems_version: 1.8.23
|
75
|
+
signing_key:
|
76
|
+
specification_version: 3
|
77
|
+
summary: Generates magic thumbnail images.
|
78
|
+
test_files: []
|