ext/rfreeimage/rfi_main.c in rfreeimage-0.1.6 vs ext/rfreeimage/rfi_main.c in rfreeimage-0.1.7
- old
+ new
@@ -83,11 +83,12 @@
}
return h;
}
static void
-rd_image(VALUE clazz, VALUE file, struct native_image *img, unsigned int bpp, BOOL ping)
+rd_image(VALUE clazz, VALUE file, struct native_image *img, unsigned int bpp, BOOL ping,
+ int max_size_hint)
{
char *filename;
int flags = 0;
FIBITMAP *h = NULL, *orig = NULL;
FREE_IMAGE_FORMAT in_fif;
@@ -97,12 +98,15 @@
in_fif = FreeImage_GetFileType(filename, 0);
if (in_fif == FIF_UNKNOWN) {
free(filename);
rb_raise(rb_eIOError, "Invalid image file");
}
+ if (max_size_hint < 0 || max_size_hint > 65535)
+ rb_raise(rb_eArgError, "Invalid max_size_hint");
if (ping) flags |= FIF_LOAD_NOPIXELS;
+ if (!ping) flags |= max_size_hint << 16;
// use JPEG_ACCURATE to keep sync with opencv
if (in_fif == FIF_JPEG)
flags |= JPEG_EXIFROTATE | JPEG_ACCURATE;
orig = FreeImage_Load(in_fif, filename, flags);
free(filename);
@@ -123,11 +127,11 @@
img->stride = FreeImage_GetPitch(h);
img->fif = in_fif;
}
static void
-rd_image_blob(VALUE clazz, VALUE blob, struct native_image *img, unsigned int bpp, BOOL ping)
+rd_image_blob(VALUE clazz, VALUE blob, struct native_image *img, unsigned int bpp, BOOL ping, int max_size_hint)
{
FIBITMAP *h = NULL, *orig = NULL;
FIMEMORY *fmh;
int flags = 0;
FREE_IMAGE_FORMAT in_fif;
@@ -138,12 +142,15 @@
in_fif = FreeImage_GetFileTypeFromMemory(fmh, 0);
if (in_fif == FIF_UNKNOWN) {
FreeImage_CloseMemory(fmh);
rb_raise(rb_eIOError, "Invalid image blob");
}
+ if (max_size_hint < 0 || max_size_hint > 65535)
+ rb_raise(rb_eArgError, "Invalid max_size_hint");
if (ping) flags |= FIF_LOAD_NOPIXELS;
+ if (!ping) flags |= max_size_hint << 16;
if (in_fif == FIF_JPEG)
flags |= JPEG_EXIFROTATE | JPEG_ACCURATE;
orig = FreeImage_LoadFromMemory(in_fif, fmh, flags);
FreeImage_CloseMemory(fmh);
if (!orig)
@@ -172,15 +179,18 @@
Data_Get_Struct(self, struct native_image, img);
switch (argc)
{
case 1:
- rd_image(self, argv[0], img, 0, 0);
+ rd_image(self, argv[0], img, 0, 0, 0);
break;
case 2:
- rd_image(self, argv[0], img, NUM2INT(argv[1]), 0);
+ rd_image(self, argv[0], img, NUM2INT(argv[1]), 0, 0);
break;
+ case 3:
+ rd_image(self, argv[0], img, NUM2INT(argv[1]), 0, NUM2INT(argv[2]));
+ break;
default:
rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
break;
}
@@ -435,10 +445,64 @@
nh = FreeImage_Rescale(img->handle, w, h, f);
return rfi_get_image(nh);
}
+VALUE Image_downscale(VALUE self, VALUE max_size) {
+ // down-sample resize
+ struct native_image *img;
+ FIBITMAP *nh;
+ int i;
+ int j;
+ int w;
+ int h;
+ int scale;
+ int mlen;
+ int msize = NUM2INT(max_size);
+
+ Data_Get_Struct(self, struct native_image, img);
+ RFI_CHECK_IMG(img);
+
+ mlen = img->w > img->h ? img->w : img->h;
+ if (msize <= 0 || msize >= mlen) {
+ nh = FreeImage_Copy(img->handle, 0, 0, img->w, img->h);
+ } else {
+ unsigned char *ph;
+ unsigned char *pnh;
+ int dst_stride;
+ if (img->bpp != 8 && img->bpp != 32)
+ rb_raise(rb_eArgError, "bpp not supported");
+
+ scale = (mlen + msize - 1) / msize;
+ w = img->w / scale;
+ h = img->h / scale;
+ nh = FreeImage_Allocate(w, h, img->bpp, 0, 0, 0);
+ if (!nh)
+ rb_raise(rb_eArgError, "fail to allocate image");
+
+ ph = FreeImage_GetBits(img->handle);
+ pnh = FreeImage_GetBits(nh);
+ dst_stride = FreeImage_GetPitch(nh);
+ if (img->bpp == 8) {
+ for(i = 0; i < h; i++) {
+ for(j = 0; j < w; j++)
+ *(pnh + j) = *(ph + j * scale);
+ ph += img->stride * scale;
+ pnh += dst_stride;
+ }
+ } else if (img->bpp == 32) {
+ for(i = 0; i < h; i++) {
+ for(j = 0; j < w; j++)
+ *((unsigned int*)pnh + j) = *((unsigned int*)ph + j * scale);
+ ph += img->stride * scale;
+ pnh += dst_stride;
+ }
+ }
+ }
+ return rfi_get_image(nh);
+}
+
VALUE Image_crop(VALUE self, VALUE _left, VALUE _top, VALUE _right, VALUE _bottom)
{
struct native_image *img;
FIBITMAP *nh;
int left = NUM2INT(_left);
@@ -464,11 +528,11 @@
VALUE Image_ping(VALUE self, VALUE file)
{
ALLOC_NEW_IMAGE(v, img);
- rd_image(self, file, img, 0, 1);
+ rd_image(self, file, img, 0, 1, 0);
if (img->handle)
FreeImage_Unload(img->handle);
img->handle = NULL;
return v;
@@ -479,15 +543,18 @@
ALLOC_NEW_IMAGE(v, img);
switch (argc)
{
case 1:
- rd_image_blob(self, argv[0], img, 0, 0);
+ rd_image_blob(self, argv[0], img, 0, 0, 0);
break;
case 2:
- rd_image_blob(self, argv[0], img, NUM2INT(argv[1]), 0);
+ rd_image_blob(self, argv[0], img, NUM2INT(argv[1]), 0, 0);
break;
+ case 3:
+ rd_image_blob(self, argv[0], img, NUM2INT(argv[1]), 0, NUM2INT(argv[2]));
+ break;
default:
rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
break;
}
@@ -496,11 +563,11 @@
VALUE Image_ping_blob(VALUE self, VALUE blob)
{
ALLOC_NEW_IMAGE(v, img);
- rd_image_blob(self, blob, img, 0, 1);
+ rd_image_blob(self, blob, img, 0, 1, 0);
if (img->handle)
FreeImage_Unload(img->handle);
img->handle = NULL;
return v;
@@ -633,9 +700,10 @@
rb_define_method(Class_Image, "release", Image_release, 0);
rb_define_method(Class_Image, "to_bpp", Image_to_bpp, 1);
rb_define_method(Class_Image, "rotate", Image_rotate, 1);
rb_define_method(Class_Image, "rescale", Image_rescale, 3);
+ rb_define_method(Class_Image, "downscale", Image_downscale, 1);
rb_define_method(Class_Image, "crop", Image_crop, 4);
rb_define_method(Class_Image, "to_blob", Image_to_blob, 1);
/* draw */
rb_define_method(Class_Image, "draw_point", Image_draw_point, 4);