Permalink
Browse files

noise stuff

  • Loading branch information...
1 parent 703f4f0 commit e60bb9b9ac897e18a37946e1cd60c2e593a307f9 @austintaylor committed Aug 10, 2009
View
@@ -1,28 +1,25 @@
-# -*- encoding: utf-8 -*-
-
Gem::Specification.new do |s|
s.name = %q{acrylic}
s.version = "0.1.0"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Austin Taylor", "Paul Nicholson"]
- s.date = %q{2009-03-10}
+ s.date = %q{2009-04-17}
s.description = %q{A set of image manipulation tools built on top of Cairo}
s.extensions = ["ext/image_surface_extensions/extconf.rb"]
- s.extra_rdoc_files = ["README"]
- s.files = ["MIT-LICENSE", "Rakefile", "README", "TODO", "VERSION.yml", "lib/acrylic.rb", "lib/border_generator.rb", "lib/cairo_tools.rb", "lib/color.rb", "lib/core_ext.rb", "lib/curve.rb", "lib/image_generator.rb", "lib/image_surface_extensions.rb", "lib/pascal.rb", "lib/shape.rb", "lib/text_box.rb", "test/bump_map_test.rb", "test/cairo_tools_test.rb", "test/color_test.rb", "test/surface.png", "test/test_helper.rb", "ext/image_surface_extensions/native_image_surface_extensions.c", "ext/image_surface_extensions/extconf.rb"]
+ s.files = ["MIT-LICENSE", "Rakefile", "README", "TODO", "VERSION.yml", "lib/acrylic.rb", "lib/border_generator.rb", "lib/cairo_tools.rb", "lib/color.rb", "lib/core_ext.rb", "lib/curve.rb", "lib/image_generator.rb", "lib/image_surface_extensions.rb", "lib/pascal.rb", "lib/pdf_generator.rb", "lib/shape.rb", "lib/text_box.rb", "test/bump_map_test.rb", "test/cairo_tools_test.rb", "test/color_test.rb", "test/surface.png", "test/test_helper.rb", "ext/image_surface_extensions/native_image_surface_extensions.c", "ext/image_surface_extensions/extconf.rb"]
s.has_rdoc = true
s.homepage = %q{http://github.com/dotjerky/acrylic}
s.rdoc_options = ["--inline-source", "--charset=UTF-8"]
s.require_paths = ["lib"]
- s.rubygems_version = %q{1.3.1}
+ s.rubygems_version = %q{1.2.0}
s.summary = %q{Photoshop for cool people.}
if s.respond_to? :specification_version then
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
s.specification_version = 2
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
+ if current_version >= 3 then
s.add_runtime_dependency(%q<activesupport>, [">= 0"])
else
s.add_dependency(%q<activesupport>, [">= 0"])
@@ -321,7 +321,7 @@ static VALUE method_render_noise(VALUE self) {
return Qnil;
}
-// cr.get_values(x, y)
+// surface.get_values(x, y)
static VALUE method_get_values(VALUE self, VALUE _x, VALUE _y) {
int x = FIX2INT(_x);
int y = FIX2INT(_y);
@@ -335,6 +335,21 @@ static VALUE method_get_values(VALUE self, VALUE _x, VALUE _y) {
return UINT2NUM(*pixel);
}
+// surface.set_values(x, y, color)
+static VALUE method_set_values(VALUE self, VALUE _x, VALUE _y, VALUE _color) {
+ int x = FIX2INT(_x);
+ int y = FIX2INT(_y);
+ unsigned int pixel = NUM2UINT(_color);
+
+ cairo_surface_t *surface = RVAL2CRSURFACE(self);
+ unsigned int *data = cairo_image_surface_get_data(surface);
+ int width = cairo_image_surface_get_width(surface);
+ int height = cairo_image_surface_get_height(surface);
+ if (x > width || y > height || x < 0 || y < 0) return Qnil;
+ data[y*width + x] = pixel;
+ return Qnil;
+}
+
void Init_native_image_surface_extensions() {
VALUE cKlass = rb_cObject;
cKlass = rb_const_get(cKlass,rb_intern("Cairo"));
@@ -346,4 +361,5 @@ void Init_native_image_surface_extensions() {
rb_define_method(cKlass, "downsample", (VALUE(*)(ANYARGS))method_downsample, 1);
rb_define_method(cKlass, "render_noise", (VALUE(*)(ANYARGS))method_render_noise, 0);
rb_define_method(cKlass, "get_values", (VALUE(*)(ANYARGS))method_get_values, 2);
+ rb_define_method(cKlass, "set_values", (VALUE(*)(ANYARGS))method_set_values, 3);
}
View
@@ -1,9 +1,10 @@
require 'rubygems'
-require 'active_support'
+require 'active_support' unless defined?(ActiveSupport)
require 'cairo'
require 'image_surface_extensions'
require 'image_generator'
require 'curve'
require 'border_generator'
+require 'pdf_generator'
module Acrylic; end
@@ -2,7 +2,6 @@
require 'color'
class Cairo::ImageSurface
-
def get_pixel(x, y)
integer = get_values(x, y)
a = integer >> 24 & 0xFF
@@ -11,4 +10,14 @@ def get_pixel(x, y)
b = integer & 0xFF
Color::RGB.new([r, g, b, a].map {|v| v.to_f/255})
end
+
+ def set_pixel(x, y, color)
+ color = color.to_rgb
+ integer = 0
+ integer |= (color.a * 255).to_i << 24
+ integer |= (color.r * 255).to_i << 16
+ integer |= (color.g * 255).to_i << 8
+ integer |= (color.b * 255).to_i
+ set_values(x, y, integer)
+ end
end
View
@@ -0,0 +1,135 @@
+require 'cairo_tools'
+require 'shape'
+class PdfGenerator
+ include Color
+ include CairoTools
+ attr_accessor :preview
+
+ def self.colors
+ @@colors ||= {}
+ end
+
+ def self.color(name, color)
+ color = color.respond_to?(:to_hsl) ? color.to_hsl : Color::HSL.new(color)
+ colors[name] = color
+ self.class_eval <<-"end;"
+ def #{name}
+ self.class.colors[:#{name}]
+ end
+ def #{name}!(a=nil)
+ set_color(a ? #{name}.a(a) : #{name})
+ end
+ end;
+ end
+
+ color :black, '000'
+ color :white, 'FFF'
+
+ def self.shapes
+ @@shapes ||= {}
+ end
+
+ def self.shape(name, width, height, &block)
+ shapes[name] = shape = Shape.new(name, width, height, block)
+ define_method("draw_#{name}") do |x, y|
+ shape.draw(cr, x, y)
+ end
+ end
+
+ def self.generate_pdf(path, *options)
+ new.generate_pdf(path, options)
+ end
+
+ def self.generate_png(path, size, *options)
+ new.generate_png(path, size, *options)
+ end
+
+ def self.preview(*options)
+ return unless $0.match(/#{name.underscore}.rb$/)
+ path = File.join(File.dirname($0), "generated.pdf")
+ options = Array(yield) if block_given?
+ instance = self.new
+ instance.preview = true
+ instance.generate_pdf(path, *options)
+ `open #{path}`
+ end
+
+
+ def self.standard_preview
+ preview(&method(:load_most_interesting_organization))
+ end
+
+ def self.load_most_interesting_organization
+ ENV["RAILS_ENV"] = "development"
+ require File.expand_path(File.dirname($0) + '/../../config/environment')
+ Organization.find(Organization.connection.select_value("select organization_id, count(id) from families where address != '' group by organization_id order by count(id) desc limit 1"))
+ end
+
+ def initialize
+ @hard_references = []
+ end
+
+ def generate_pdf(path, options)
+ @canvas_width, @canvas_height = paper_size.map(&:in)
+ @page_number = 1
+ @surface = Cairo::PDFSurface.new(path, canvas_width, canvas_height)
+ @cr = Cairo::Context.new(surface)
+ margin 0
+ paint_background
+ draw(*options)
+ cr.target.finish
+ end
+
+ def generate_png(path, size, options)
+ @one_page = true
+ png_width, png_height = size
+ @paper_width, @paper_height = paper_size.map(&:in)
+ initialize_margins
+ @surface = Cairo::ImageSurface.new(png_width, png_height)
+ @cr = Cairo::Context.new(surface)
+ @cr.scale(png_width.to_f/paper_width, png_height.to_f/paper_height)
+ paint_background
+ draw(*options)
+ cr.target.write_to_png(path)
+ end
+
+ def paper_size
+ [8.5, 11]
+ end
+
+ def paint_background
+ white!
+ cr.paint
+ end
+
+ def include_pdf(name, *args)
+ "#{name.to_s}_pdf".classify.constantize.new.draw_on(self, *args)
+ end
+
+ def end_page(numbered=true)
+ show_page_number && @page_number += 1 if numbered
+ cr.show_page
+ end
+
+ def show_page_number
+ draw_text_box(left_margin, top_margin + height, width) do |tb|
+ tb.line(@page_number.to_s, :face => 'Times New Roman', :size => 12, :align => :center)
+ end
+ end
+
+ def draw_on(pdf, *args)
+ @paper_width, @paper_height, @surface, @cr, @page_number = pdf.paper_width, pdf.paper_height, pdf.surface, pdf.cr, pdf.page_number
+ @hard_references = pdf.hard_references
+ initialize_margins
+ paint_background
+ draw(*args)
+ pdf.page_number = @page_number
+ end
+end
+
+class Numeric
+ def in
+ self * 72
+ end
+end
+
View
@@ -0,0 +1,147 @@
+require '../lib/acrylic'
+
+class Texture
+ def initialize(proc)
+ @proc = proc
+ end
+
+ def generate_surface(w, h)
+ @surface = Cairo::ImageSurface.new(w, h)
+ 0.upto(h) do |y|
+ 0.upto(w) do |x|
+ @surface.set_pixel(x, y, color_for(pixel(x, y)))
+ end
+ end
+ end
+
+ def pixel(x, y)
+ @proc.call(x.to_f, y.to_f)
+ end
+
+ def color_for(return_value)
+ case return_value
+ when Color::Base
+ return_value
+ end
+ end
+
+ def surface(w, h)
+ generate_surface(w, h) if !@surface
+ @surface
+ end
+end
+
+class NoiseTexture < Texture
+ def initialize
+ @p = (0..255).to_a.sort_by {rand}
+ @g2 = (0..255).map do |i|
+ normalize2(random_component, random_component)
+ end
+ end
+
+ def random_component
+ (rand(512) - 256).to_f / 256
+ end
+
+ def normalize2(x, y)
+ s = Math.sqrt(x * x + y * y)
+ [x/s, y/s]
+ end
+
+ def gradients_for(x, y)
+ bx0, by0 = x.floor & 255, y.floor & 255
+ bx1, by1 = (bx0 + 1) & 255, (by0 + 1) & 255
+ i, j = @p[bx0], @p[bx1]
+ [i + by0, j + by0, i + by1, j + by1].map {|i| @g2[@p[i & 255]]}
+ end
+
+ def at2(x, y, gradient)
+ x * gradient[0] + y * gradient[1]
+ end
+
+ def s_curve(t)
+ t * t * (3.0 - 2.0 * t)
+ end
+
+ def lerp(t, a, b)
+ a + t * (b - a)
+ end
+
+ def noise(x, y)
+ g00, g10, g01, g11 = gradients_for(x, y)
+ rx0, ry0 = x - x.floor, y - y.floor
+ rx1, ry1 = rx0 - 1, ry0 - 1
+ sx, sy = s_curve(rx0), s_curve(ry0)
+
+ u = at2(rx0, ry0, g00)
+ v = at2(rx1, ry0, g10)
+ a = lerp(sx, u, v)
+
+ u = at2(rx0, ry1, g01)
+ v = at2(rx1, ry1, g11)
+ b = lerp(sx, u, v)
+
+ lerp(sy, a, b)
+ end
+
+ def fractal_noise(x, y, iterations)
+ power = 0
+ result = 0
+ iterations.times do
+ coefficient = 2 ** power
+ result += (1.0 / coefficient) * noise(x * coefficient, y * coefficient)
+ power += 1
+ end
+ result
+ end
+
+ def pixel(x, y)
+ x, y = x.to_f/100, y.to_f/100
+ value = fractal_noise(x, y, 6)
+ # @gradient ||= Gradient.new([0.6, 0.6, 0.7], [0.6, 0, 1])
+ @gradient ||= Gradient.new('#E2D9C0', '#7E5D40')
+ z = x * 50
+ y = y * 200
+ distance = Math.sqrt((50 - z) ** 2 + (50 - y) ** 2)
+ p distance
+ @gradient.at((Math.sin(distance - value) + 1) / 2)
+ end
+end
+
+class Gradient
+ def initialize(one, two)
+ @one = Color::HSL.new(one)
+ @two = Color::HSL.new(two)
+ end
+
+ def at(t)
+ components = %w(h s l a).map do |c|
+ @one.send(c) + (@two.send(c) - @one.send(c)) * t
+ end
+ Color::HSL.new(components)
+ end
+end
+
+class Noise < ImageGenerator
+ def self.texture(name, texture=nil, &block)
+ define_method(name) do
+ texture || Texture.new(block)
+ end
+ end
+
+ texture :noise, NoiseTexture.new
+
+ def fill_with(texture)
+ cr.set_source Cairo::SurfacePattern.new(texture.surface(@canvas_width, @canvas_height))
+ cr.fill
+ end
+
+ image :test do
+ dimensions 100, 100
+ cr.rectangle 0, 0, width, height
+ # black!
+ # cr.fill
+ fill_with noise
+ end
+ preview :test
+end

0 comments on commit e60bb9b

Please sign in to comment.