diff --git a/lib/image_science.rb b/lib/image_science.rb index 1124092..c26c8e6 100755 --- a/lib/image_science.rb +++ b/lib/image_science.rb @@ -19,6 +19,12 @@ class ImageScience def self.with_image(path) # :yields: image end + ## + # The top-level image loader, opens an image from the string +data+ and then yields the image. + + def self.with_image_from_memory(data) # :yields: image + end + ## # Crops an image to +left+, +top+, +right+, and +bottom+ and then # yields the new image. @@ -158,6 +164,36 @@ def cropped_thumbnail(size) # :yields: image } END + builder.c_singleton <<-"END" + VALUE with_image_from_memory(VALUE image_data) { + FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; + + Check_Type(image_data, T_STRING); + BYTE *image_data_ptr = (BYTE*)RSTRING(image_data)->ptr; + DWORD image_data_length = RSTRING(image_data)->len; + FIMEMORY *stream = FreeImage_OpenMemory(image_data_ptr, image_data_length); + + if (NULL == stream) { + rb_raise(rb_eTypeError, "Unable to open image_data"); + } + + fif = FreeImage_GetFileTypeFromMemory(stream, 0); + if ((fif == FIF_UNKNOWN) || !FreeImage_FIFSupportsReading(fif)) { + rb_raise(rb_eTypeError, "Unknown file format"); + } + + FIBITMAP *bitmap = NULL; + VALUE result = Qnil; + int flags = fif == FIF_JPEG ? JPEG_ACCURATE : 0; + bitmap = FreeImage_LoadFromMemory(fif, stream, flags); + FreeImage_CloseMemory(stream); + if (bitmap) { + result = wrap_and_yield(bitmap, self, fif); + } + return result; + } + END + builder.c <<-"END" VALUE with_crop(int l, int t, int r, int b) { FIBITMAP *copy; diff --git a/test/test_image_science.rb b/test/test_image_science.rb index 2b48e32..05454d0 100644 --- a/test/test_image_science.rb +++ b/test/test_image_science.rb @@ -46,6 +46,33 @@ def test_class_with_image_missing_with_img_extension end end + def test_class_with_image_from_memory + data = File.new(@path).binmode.read + + ImageScience.with_image_from_memory data do |img| + assert_kind_of ImageScience, img + assert_equal @h, img.height + assert_equal @w, img.width + assert img.save(@tmppath) + end + + assert File.exists?(@tmppath) + + ImageScience.with_image @tmppath do |img| + assert_kind_of ImageScience, img + assert_equal @h, img.height + assert_equal @w, img.width + end + end + + def test_class_with_image_from_memory_empty_string + assert_raises TypeError do + ImageScience.with_image_from_memory "" do |img| + flunk + end + end + end + def test_resize ImageScience.with_image @path do |img| img.resize(25, 25) do |thumb|