We’ve (Ron Evans and myself) have been working hard to release a new gem called ProcessorPool that uses EC2 and S3 to run your processor heavy-lifting!
Check it out at Blog @ CitrusByte
Where it all started
February 20th, 2008 — code, ruby, rails, tutorial
We’ve (Ron Evans and myself) have been working hard to release a new gem called ProcessorPool that uses EC2 and S3 to run your processor heavy-lifting!
Check it out at Blog @ CitrusByte
November 14th, 2007 — Blogroll, code, tutorial
In writing a compiler, I’ve come across a sleek part of the standard c library that I just can’t help and a take a few minutes to write a blog post about it!
You can send any number of arguments to a method / macro that you want. It’s called Variadic methods and they have a crazy syntax. Here is a piece of code that I am using in the compiler. It’s super similar to the printf method (the printf method itself is a variadic method, if you’ve ever wondered…)
char *stringerize(const char *fmt, ...) {
char *buf = safe_malloc(sizeof(char)*BUFSIZE);
va_list args;
va_start(args, fmt);
if (args && strlen(args) > 0)
(void) vsnprintf(buf, BUFSIZE, fmt, args);
va_end(args);
return (buf);
}
Kind uninteresting, huh? I’ll show you a much more interesting one at the end of the post thatallows you to safely concatenate any number of strings.
The basic idea is that you define a method with the … syntax, such as
char *stringerize(const char *fmt, ...)
...
There are two two ways to access those variables.
One by one
First, you declare all your variables that you are going to use in the method. That has to be before accessing the list. Then, you start the list with
va_list args;
Make sure you don’t forget to declare the args as a list otherwise C will throw a fit.
Then, when you are ready to get the variables, call
va_start(args, fmt);
The second parameter is the last required argument in the command. You do need at least one required argument in a function. The same requirement does not hold true for macros, though.
Then, to get to the variable you call
va_arg(args, const char *);
The second parameter is the type you are expecting to come back. This gives C a heads up as to what to expect.
Then, when you are done and want to move on to the next one in the list, simply call:
va_end(args);
That’s it!
Accessing the variables all at once
You can either do this in a macro that would look something like (untested):
#define VARGS(...) fprintf(stderr, __VA_ARGS__)
// or
#define VARGS(fmt, args...) fprintf(stderr, fmt, args)
There are other ways as well, but those are the ones that stood out to me. In a method, you can do this as I had done in the example above. Just call list and all the arguments are accessible to you, right there in your shirt pocket!
And now, finally for the more important snippet that:
char *concat_commands(const char* str,...) {
va_list args; char *s; size_t held_memory = 100;
char *res = safe_malloc(sizeof(char)*held_memory);
if (res != NULL) {
char *new_pointer, *word_pointer;
va_start(args, str);
word_pointer = res;
for (s=str;s!=NULL;s=va_arg(args, const char *)) {
size_t len = strlen(s);
if (word_pointer + len + 1 > res + held_memory) {
held_memory = (held_memory + len) * 2;
new_pointer = (char *) realloc (res, held_memory);
if (new_pointer == NULL) { free(res); return NULL; }
word_pointer = new_pointer + (word_pointer - res);
res = new_pointer;
}
word_pointer = memcpy(word_pointer,s,len);
word_pointer = word_pointer + len;
}
*word_pointer++ = ' ';
new_pointer = (char *) realloc(res, word_pointer-res);
if (new_pointer != NULL) {res = new_pointer;}
va_end(args);
}
return res;
}
I hope this helps someone out there save a few hours and remember how cool C even in the midst of the ruby we all love so much. On that note, I urge you to look at the ruby interpreter source code. It’s a tad jumbled up, my guess is because there are a few people working on it, but it is sure damn sexy code. Thanks once again matz!
I’ll be back more in a week or so for more fervent posts after my compiler is done.
April 30th, 2007 — code, random, life, ruby, rmagick, tutorial
LA adventures
I have been in Los Angeles for the past several days doing some work with… well, my work. I promised a friend I would help him out with his graphics. Unfortunately, I am on a plane and also on a laptop that does not have photoshop/illustrator so I can’t do any work with it now. I had planned on doing some homework up here, but rather than doing that, I think it’s probably a fun idea to try to see what I can do design-wise with a little bit of code. Ooo, could be fun.
Let’s get started.
First off, the project I am helping him out with is a graphics project. He is assigned to develop and brand a music publishing company for a class of his. We had come up with a name and a graphic, so let’s actually design it.
The name of the company is R3CORDS. We can easily create an image using ruby and rmagick:
require 'rubygems'
require "RMagick"
string = "R3cords".upcase
# prepare drawing surface
text = Magick::Draw.new
text.fill = 'white'
text.pointsize = 40
# Create and composite the images
temp_image = Magick::Image.new(w, h) { self.background_color = "none" }
temp_image = temp_image.annotate(text, 0, 0, 5, 40, string)
# WRITE OUT
temp_image.format = "JPG"
temp_image.write('temp.jpg')
As you can see, we are just creating an RMagick Drawing object, telling it a few things we want to look like, such as the background color of the image. We say we want white text against a “none” (black) color background and then we write the text out at 5 pixels from the left and 40 from the top. The pointsize is 40. Then we write it out to an image and we are done, right?
No way, I’m stuck on a plane and there is so much more we can do, let’s not stop here, ey?
Let’s make the logo a little more “recordy.” We’ll add a small outline to the logo text and give the font a weight that makes it stand out a little more:
text.stroke = 'black'
text.stroke_width = 1
OO, that looks fun. Oh, but there is still more! We are going to put this on top of another image and kind of blend it in. The only way a black background would work is if the image were black, and it’s not (which you’ll see in a few minutes).
So rather than using a black background, we’ll change a few things and make it even cooler with a transparent background and perhaps a shadow.
# prepare drawing surface
text = Magick::Draw.new
text.fill = 'white'
text.pointsize = 40
text.font_weight = 800
text.stroke_width = 0
temp_image = Magick::Image.new(w, h) { self.background_color = "transparent" }
temp_image = temp_image.annotate(text, 0, 0, 5, 40, string)
# Make the shadow
shadow = temp_image
shadow = shadow.colorize(1, 1, 8, Magick::Pixel.new(100, 100, 100, 20)) # shadow color can vary to taste
shadow.background_color = "grey24" # was "none"
shadow.border!(4, 4, "white")
shadow = shadow.blur_image(0, 3) # shadow blurriness can vary according to taste
# Composite image over shadow. The y-axis adjustment can vary according to taste.
temp_image = shadow.composite(temp_image, -amplitude, 0, Magick::OverCompositeOp)
OO, weee. So now we added a shadow over the temp_image and took out the background of the other. In order to get this on top of another image, we have to open the new image and composite it on top.
I think we are close to finished with the logo, but I want to add one more cool thing to it.
I wanted to add some neat funky-looking boxes to make it look tech-cool.
Where do we start? Well, I’ve already done it
# Lets create a cool background behind it
neat = Magick::ImageList.new
neat.new_image(background_image.columns, background_image.rows) {
self.background_color = 'transparent'
}
1.upto(background_image.rows) do |i|
c = Magick::Image.new(1, 1+rand(25)) do |m|
m.background_color = '#cccccc'
end
c.rotate!(i*rand(360))
neat.composite!(c, i*rand(5), i+rand(background_image.rows), Magick::OverCompositeOp)
end
And we are done
The full code is down below.
Finished, just in time for beverage service
Oh, and LA was sweet.
require 'rubygems'
require "RMagick"
w = 200
h = 100
string = "R3cords".upcase
amplitude = h * 0.01 # vary according to taste
wavelength = w * 2
temp_image = Magick::Image.new(w*2, h) { self.background_color = "transparent" }
# Make the shadow
shadow = temp_image
shadow = shadow.colorize(1, 1, 8, "#883333") # shadow color can vary to taste
shadow.border!(4, 1, "transparent")
shadow = shadow.blur_image(0, 10) # shadow blurriness can vary according to taste
temp_image = shadow.composite(temp_image, 0, 0, Magick::OverCompositeOp)
# Let's set this aside for a moment and do..
background_image = Magick::Image.read("bg.jpg").first
temp_image = background_image.composite(temp_image, Magick::SouthEastGravity, Magick::OverCompositeOp)
# Lets create a cool background behind it
neat = Magick::ImageList.new
neat.new_image(background_image.columns, background_image.rows) {
self.background_color = 'transparent'
}
1.upto(background_image.rows) do |i|
c = Magick::Image.new(1, 1+rand(25)) do |m|
m.background_color = '#cccccc'
end
c.rotate!(i*rand(360))
neat.composite!(c, i*rand(5), i+rand(background_image.rows), Magick::OverCompositeOp)
end
temp_image = temp_image.dissolve(neat, 0.2, 4.9)
# prepare drawing surface
text = Magick::Draw.new
text.fill = 'white'
# text.text_antialias = false
text.pointsize = 80
# text.rotation = 0
text.font_family = "Helvetica"
text.font_weight = 800
text.stroke_width = 1
text.stroke = 'black'
text.gravity = Magick::SouthEastGravity
temp_image = temp_image.annotate(text, 0, 0, 0, 0, string)
# WRITE OUT
temp_image.format = "JPG"
# self.rmagick_image = canvas
temp_image.write('temp.jpg')
All done entirely without a photo editor. Just one sweet computer and a kick-butt text editor!
I enjoyed this tutorial. I think I’ll write some more in the future. Let me know if it was helpful.