From 006f7afc9efc533175af7eba679998af948adfa3 Mon Sep 17 00:00:00 2001 From: Matthias Kramm Date: Tue, 22 Dec 2009 17:14:50 -0800 Subject: [PATCH] moved image rescaler to lib/gfximage.c --- lib/Makefile.in | 4 +- lib/devices/swf.c | 6 +- lib/gfximage.c | 342 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/gfximage.h | 10 ++ lib/gfxtools.c | 15 --- lib/gfxtools.h | 2 - lib/modules/swfbits.c | 307 -------------------------------------------- lib/pdf/pdf.cc | 8 +- lib/rfxswf.h | 1 - lib/ruby/gfx.c | 33 ++++- 10 files changed, 393 insertions(+), 335 deletions(-) create mode 100644 lib/gfximage.c create mode 100644 lib/gfximage.h diff --git a/lib/Makefile.in b/lib/Makefile.in index f075ae4..3c8fa52 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -19,7 +19,7 @@ gfxpoly_objects = gfxpoly/active.$(O) gfxpoly/convert.$(O) gfxpoly/poly.$(O) gfx rfxswf_modules = modules/swfbits.c modules/swfaction.c modules/swfdump.c modules/swfcgi.c modules/swfbutton.c modules/swftext.c modules/swffont.c modules/swftools.c modules/swfsound.c modules/swfshape.c modules/swfobject.c modules/swfdraw.c modules/swffilter.c modules/swfrender.c h.263/swfvideo.c modules/swfalignzones.c base_objects=q.$(O) utf8.$(O) png.$(O) jpeg.$(O) wav.$(O) mp3.$(O) os.$(O) bitio.$(O) log.$(O) mem.$(O) MD5.$(O) -gfx_objects=gfxtools.$(O) gfxfont.$(O) devices/dummy.$(O) devices/file.$(O) devices/render.$(O) devices/text.$(O) devices/record.$(O) devices/ops.$(O) devices/polyops.$(O) devices/bbox.$(O) devices/rescale.$(O) @DEVICE_OPENGL@ @DEVICE_PDF@ +gfx_objects=gfximage.$(O) gfxtools.$(O) gfxfont.$(O) devices/dummy.$(O) devices/file.$(O) devices/render.$(O) devices/text.$(O) devices/record.$(O) devices/ops.$(O) devices/polyops.$(O) devices/bbox.$(O) devices/rescale.$(O) @DEVICE_OPENGL@ @DEVICE_PDF@ rfxswf_objects=modules/swfaction.$(O) modules/swfbits.$(O) modules/swfbutton.$(O) modules/swfcgi.$(O) modules/swfdraw.$(O) modules/swfdump.$(O) modules/swffilter.$(O) modules/swffont.$(O) modules/swfobject.$(O) modules/swfrender.$(O) modules/swfshape.$(O) modules/swfsound.$(O) modules/swftext.$(O) modules/swftools.$(O) modules/swfalignzones.$(O) ocr_objects=gocr/box.$(O) gocr/database.$(O) gocr/detect.$(O) gocr/job.$(O) gocr/lines.$(O) gocr/list.$(O) gocr/ocr0.$(O) gocr/ocr0n.$(O) gocr/ocr1.$(O) gocr/otsu.$(O) gocr/output.$(O) gocr/pgm2asc.$(O) gocr/pixel.$(O) gocr/progress.$(O) gocr/remove.$(O) gocr/unicode.$(O) @@ -85,6 +85,8 @@ modules/swftext.$(O): modules/swftext.c rfxswf.h $(C) modules/swftext.c -o $@ modules/swftools.$(O): modules/swftools.c rfxswf.h $(C) modules/swftools.c -o $@ +gfximage.$(O): gfximage.c gfximage.h gfxdevice.h $(top_builddir)/config.h + $(C) gfximage.c -o $@ gfxtools.$(O): gfxtools.c gfxtools.h $(top_builddir)/config.h $(C) gfxtools.c -o $@ gfxfont.$(O): gfxfont.c gfxfont.h $(top_builddir)/config.h diff --git a/lib/devices/swf.c b/lib/devices/swf.c index ad21d78..3be81d5 100644 --- a/lib/devices/swf.c +++ b/lib/devices/swf.c @@ -42,7 +42,7 @@ #include "../gfxtools.h" #include "swf.h" #include "../gfxpoly.h" -#include "../png.h" +#include "../gfximage.h" #define CHARDATAMAX 1024 #define CHARMIDX 0 @@ -2255,7 +2255,9 @@ static int add_image(swfoutput_internal*i, gfximage_t*img, int targetwidth, int if(newsizex Scaling %dx%d image to %dx%d", sizex, sizey, newsizex, newsizey); - newpic = swf_ImageScale(mem, sizex, sizey, newsizex, newsizey); + gfximage_t*ni = gfximage_rescale(img, newsizex, newsizey); + newpic = (RGBA*)ni->data; + free(ni); *newwidth = sizex = newsizex; *newheight = sizey = newsizey; mem = newpic; diff --git a/lib/gfximage.c b/lib/gfximage.c new file mode 100644 index 0000000..54adadc --- /dev/null +++ b/lib/gfximage.c @@ -0,0 +1,342 @@ +#include +#include +#include "jpeg.h" +#include "png.h" +#include "mem.h" +#include "gfximage.h" +#include "types.h" + +void gfximage_save_jpeg(gfximage_t*img, int quality, const char*filename) +{ + int x,y; + int l = img->width*img->height; + unsigned char*data = (unsigned char*)rfx_alloc(img->width*img->height*3); + int s,t; + for(t=0,s=0;tdata[t].r; + data[s+1] = img->data[t].g; + data[s+2] = img->data[t].b; + } + jpeg_save(data, img->width, img->height, quality, filename); +} + +void gfximage_save_png(gfximage_t*image, const char*filename) +{ + writePNG(filename, (void*)image->data, image->width, image->height); +} + +typedef struct scale_lookup { + int pos; + unsigned int weight; +} scale_lookup_t; + +typedef struct rgba_int { + unsigned int r,g,b,a; +} rgba_int_t; + +static int bicubic = 0; + +static scale_lookup_t**make_scale_lookup(int width, int newwidth) +{ + scale_lookup_t*lookupx = (scale_lookup_t*)rfx_alloc((width>newwidth?width:newwidth)*2*sizeof(scale_lookup_t)); + scale_lookup_t**lblockx = (scale_lookup_t**)rfx_alloc((newwidth+1)*sizeof(scale_lookup_t**)); + double fx = ((double)width)/((double)newwidth); + double px = 0; + int x; + scale_lookup_t*p_x = lookupx; + + if(newwidth<=width) { + for(x=0;x=width) tox = width-1; + for(xx=fromx;xx<=tox;xx++) { + if(xx==fromx && xx==tox) p_x->weight = 256; + else if(xx==fromx) p_x->weight = xweight; + else if(xx==tox) p_x->weight = 256-w; + else p_x->weight = i; + w+=p_x->weight; + p_x->pos = xx; + p_x++; + } + px = ex; + } + } else { + for(x=0;x=width) ix2=width-1; + lblockx[x] = p_x; + if(bicubic) + r = -2*r*r*r+3*r*r; + p_x[0].weight = (int)(256*(1-r)); + p_x[0].pos = ix1; + p_x[1].weight = 256-p_x[0].weight; + p_x[1].pos = ix2; + p_x+=2; + px += fx; + } + } + lblockx[newwidth] = p_x; + return lblockx; +} + +static void encodeMonochromeImage(gfxcolor_t*data, int width, int height, gfxcolor_t*colors) +{ + int t; + int len = width*height; + + U32* img = (U32*)data; + U32 color1 = img[0]; + U32 color2 = 0; + for(t=1;t> 8; + data[t].g = (colors[0].g * (255-m) + colors[1].g * m) >> 8; + data[t].b = (colors[0].b * (255-m) + colors[1].b * m) >> 8; + data[t].a = (colors[0].a * (255-m) + colors[1].a * m) >> 8; + } +} + +void blurImage(gfxcolor_t*src, int width, int height, int r) __attribute__ ((noinline)); + +void blurImage(gfxcolor_t*src, int width, int height, int r) +{ + int e = 2; // r times e is the sampling interval + double*gauss = (double*)rfx_alloc(r*e*sizeof(double)); + double sum=0; + int x; + for(x=0;x> 16; + d[x].g = g >> 16; + d[x].b = b >> 16; + d[x].a = a >> 16; + } + for(x=width-range;x> 16; + d[yy].g = g >> 16; + d[yy].b = b >> 16; + d[yy].a = a >> 16; + yy += width; + } + for(y=0;ywidth; + int height = image->height; + gfxcolor_t*data = image->data; + + if(swf_ImageGetNumberOfPaletteEntries2(data, width, height) == 2) { + monochrome=1; + encodeMonochromeImage(data, width, height, monochrome_colors); + int r1 = width / newwidth; + int r2 = height / newheight; + int r = r14) { + /* high-resolution monochrome images are usually dithered, so + low-pass filter them first to get rid of any moire patterns */ + blurImage(data, width, height, r+1); + } + } + + tmpline = (rgba_int_t*)rfx_alloc(width*sizeof(rgba_int_t)); + newdata = (gfxcolor_t*)rfx_alloc(newwidth*newheight*sizeof(gfxcolor_t)); + + lblockx = make_scale_lookup(width, newwidth); + lblocky = make_scale_lookup(height, newheight); + + for(p=lblocky[0];ppos*=width; + + for(y=0;ypos]; + scale_lookup_t*p_x; + int weight = p_y->weight; + for(x=0;xpos]; + unsigned int weight = p_x->weight; + r += col->r*weight; + g += col->g*weight; + b += col->b*weight; + a += col->a*weight; + p_x++; + } while (p_xr = r >> 16; + destline->g = g >> 16; + destline->b = b >> 16; + destline->a = a >> 16; + + destline++; + } + } + + if(monochrome) + decodeMonochromeImage(newdata, newwidth, newheight, monochrome_colors); + + rfx_free(tmpline); + rfx_free(*lblockx); + rfx_free(lblockx); + rfx_free(*lblocky); + rfx_free(lblocky); + + gfximage_t*image2 = (gfximage_t*)malloc(sizeof(gfximage_t)); + image2->data = newdata; + image2->width = newwidth; + image2->height = newheight; + return image2; +} diff --git a/lib/gfximage.h b/lib/gfximage.h new file mode 100644 index 0000000..11545ff --- /dev/null +++ b/lib/gfximage.h @@ -0,0 +1,10 @@ +#ifndef __gfximage_h__ +#define __gfximage_h__ + +#include "gfxdevice.h" + +void gfximage_save_jpeg(gfximage_t*image, int quality, const char*filename); +void gfximage_save_png(gfximage_t*image, const char*filename); +gfximage_t* gfximage_rescale(gfximage_t*image, int newwidth, int newheight); + +#endif diff --git a/lib/gfxtools.c b/lib/gfxtools.c index 2e080de..36c9508 100644 --- a/lib/gfxtools.c +++ b/lib/gfxtools.c @@ -1137,21 +1137,6 @@ gfxline_t* gfxline_reverse(gfxline_t*line) return b; } -void gfximage_save_jpeg(gfximage_t*img, char*filename, int quality) -{ - unsigned char*data = malloc(img->width*img->height*3); - int t; - int size = img->width*img->height; - int s = 0; - for(t=0;tdata[t].r; - data[s+1] = img->data[t].g; - data[s+2] = img->data[t].b; - s+=3; - } - jpeg_save(data, img->width, img->height, quality, filename); -} - gfxparams_t* gfxparams_new() { return (gfxparams_t*)rfx_calloc(sizeof(gfxparams_t)); diff --git a/lib/gfxtools.h b/lib/gfxtools.h index 430b2e4..5c27e2b 100644 --- a/lib/gfxtools.h +++ b/lib/gfxtools.h @@ -93,8 +93,6 @@ char gfxfontlist_hasfont(gfxfontlist_t*list, gfxfont_t*font); void* gfxfontlist_getuserdata(gfxfontlist_t*list, const char*id); void gfxfontlist_free(gfxfontlist_t*list, char deletefonts); -void gfximage_save_jpeg(gfximage_t*img, char*filename, int quality); - gfxbbox_t* gfxline_isrectangle(gfxline_t*_l); gfxline_t*gfxline_makerectangle(double x1, double y1, double x2, double y2); diff --git a/lib/modules/swfbits.c b/lib/modules/swfbits.c index 4643551..1e32cf2 100644 --- a/lib/modules/swfbits.c +++ b/lib/modules/swfbits.c @@ -61,30 +61,6 @@ int swf_ImageHasAlpha(RGBA*img, int width, int height) return hasalpha; } -int swf_ImageGetNumberOfPaletteEntries2(RGBA*_img, int width, int height) -{ - int len = width*height; - int t; - U32* img = (U32*)_img; - U32 color1 = img[0]; - U32 color2 = 0; - for(t=1;tnewwidth?width:newwidth)*2*sizeof(scale_lookup_t)); - scale_lookup_t**lblockx = (scale_lookup_t**)malloc((newwidth+1)*sizeof(scale_lookup_t**)); - double fx = ((double)width)/((double)newwidth); - double px = 0; - int x; - scale_lookup_t*p_x = lookupx; - - if(newwidth<=width) { - for(x=0;x=width) tox = width-1; - for(xx=fromx;xx<=tox;xx++) { - if(xx==fromx && xx==tox) p_x->weight = 256; - else if(xx==fromx) p_x->weight = xweight; - else if(xx==tox) p_x->weight = 256-w; - else p_x->weight = i; - w+=p_x->weight; - p_x->pos = xx; - p_x++; - } - px = ex; - } - } else { - for(x=0;x=width) ix2=width-1; - lblockx[x] = p_x; - if(bicubic) - r = -2*r*r*r+3*r*r; - p_x[0].weight = (int)(256*(1-r)); - p_x[0].pos = ix1; - p_x[1].weight = 256-p_x[0].weight; - p_x[1].pos = ix2; - p_x+=2; - px += fx; - } - } - lblockx[newwidth] = p_x; - return lblockx; -} - -static void encodeMonochromeImage(RGBA*data, int width, int height, RGBA*colors) -{ - int t; - int len = width*height; - - U32* img = (U32*)data; - U32 color1 = img[0]; - U32 color2 = 0; - for(t=1;t> 8; - data[t].g = (colors[0].g * (255-m) + colors[1].g * m) >> 8; - data[t].b = (colors[0].b * (255-m) + colors[1].b * m) >> 8; - data[t].a = (colors[0].a * (255-m) + colors[1].a * m) >> 8; - } -} - -static void blurImage(RGBA*src, int width, int height, int r) -{ - int e = 2; // r times e is the sampling interval - double*gauss = (double*)malloc(r*e*sizeof(double)); - double sum=0; - int x; - for(x=0;x> 16; - d[x].g = g >> 16; - d[x].b = b >> 16; - d[x].a = a >> 16; - } - for(x=width-range;x> 16; - d[yy].g = g >> 16; - d[yy].b = b >> 16; - d[yy].a = a >> 16; - yy += width; - } - for(y=0;y4) { - /* high-resolution monochrome images are usually dithered, so - low-pass filter them first to get rid of any moire patterns */ - blurImage(data, width, height, r+1); - } - } - - tmpline = (rgba_int_t*)malloc(width*sizeof(rgba_int_t)); - newdata = (RGBA*)malloc(newwidth*newheight*sizeof(RGBA)); - - lblockx = make_scale_lookup(width, newwidth); - lblocky = make_scale_lookup(height, newheight); - - for(p=lblocky[0];ppos*=width; - - for(y=0;ypos]; - scale_lookup_t*p_x; - int weight = p_y->weight; - for(x=0;xpos]; - unsigned int weight = p_x->weight; - r += col->r*weight; - g += col->g*weight; - b += col->b*weight; - a += col->a*weight; - p_x++; - } while (p_xr = r >> 16; - destline->g = g >> 16; - destline->b = b >> 16; - destline->a = a >> 16; - - destline++; - } - } - - if(monochrome) - decodeMonochromeImage(newdata, newwidth, newheight, monochrome_colors); - - free(tmpline); - free(*lblockx); - free(lblockx); - free(*lblocky); - free(lblocky); - return newdata; -} - - diff --git a/lib/pdf/pdf.cc b/lib/pdf/pdf.cc index e6bfe14..a5371c5 100644 --- a/lib/pdf/pdf.cc +++ b/lib/pdf/pdf.cc @@ -497,9 +497,15 @@ static gfxdocument_t*pdf_open(gfxsource_t*src, const char*filename) pdf_doc->getinfo = pdf_doc_getinfo; pdf_doc->getpage = pdf_doc_getpage; pdf_doc->prepare = pdf_doc_prepare; + + /* pass global parameters to PDF driver*/ + gfxparam_t*p = isrc->parameters->params; + while(p) { + pdf_doc->setparameter(pdf_doc, p->key, p->value); + p = p->next; + } return pdf_doc; - } void pdf_destroy(gfxsource_t*src) diff --git a/lib/rfxswf.h b/lib/rfxswf.h index c2cf0e3..e42aee6 100644 --- a/lib/rfxswf.h +++ b/lib/rfxswf.h @@ -743,7 +743,6 @@ void swf_SetLosslessImage(TAG*tag, RGBA*data, int width, int height); //WARNING: RGBA* swf_DefineLosslessBitsTagToImage(TAG*tag, int*width, int*height); RGBA* swf_ExtractImage(TAG*tag, int*dwidth, int*dheight); -RGBA* swf_ImageScale(RGBA*data, int width, int height, int newwidth, int newheight); TAG* swf_AddImage(TAG*tag, int bitid, RGBA*mem, int width, int height, int quality); // swfsound.c diff --git a/lib/ruby/gfx.c b/lib/ruby/gfx.c index 6a47da7..1ba0c1e 100644 --- a/lib/ruby/gfx.c +++ b/lib/ruby/gfx.c @@ -2,6 +2,7 @@ #include "../gfxdevice.h" #include "../gfxsource.h" #include "../gfxtools.h" +#include "../gfximage.h" #include "../devices/pdf.h" #include "../readers/swf.h" #include "../readers/image.h" @@ -200,18 +201,34 @@ static VALUE image_height(VALUE cls) Get_Image(image,cls) return INT2FIX(image->image->height); } +static VALUE image_rescale(VALUE cls, VALUE _width, VALUE _height) +{ + Get_Image(image,cls) + Check_Type(_width, T_FIXNUM); + Check_Type(_height, T_FIXNUM); + int width = FIX2INT(_width); + int height = FIX2INT(_height); + volatile VALUE v_image2 = image_allocate(Bitmap); + Get_Image(image2,v_image2) + image2->doc = image->doc; + image2->image = gfximage_rescale(image->image, width, height); + return v_image2; +} static VALUE image_save_jpeg(VALUE cls, VALUE _filename, VALUE quality) { Get_Image(image,cls) Check_Type(_filename, T_STRING); Check_Type(quality, T_FIXNUM); const char*filename = StringValuePtr(_filename); - int l = strlen(filename); - char jpeg = 0; - if(l>=4 && !strcmp(&filename[l-4], ".jpg")) jpeg = 1; - if(l>=5 && !strcmp(&filename[l-5], ".jpeg")) jpeg = 1; - if(l>=4 && !strcmp(&filename[l-4], ".JPG")) jpeg = 1; - jpeg_save(image->image->data, image->image->width, image->image->height, FIX2INT(quality), filename); + gfximage_save_jpeg(image->image, FIX2INT(quality), filename); + return cls; +} +static VALUE image_save_png(VALUE cls, VALUE _filename) +{ + Get_Image(image,cls) + Check_Type(_filename, T_STRING); + const char*filename = StringValuePtr(_filename); + gfximage_save_png(image->image, filename); return cls; } VALUE convert_image(doc_internal_t*doc,gfximage_t*_image) @@ -608,6 +625,10 @@ void Init_gfx() Bitmap = rb_define_class_under(GFX, "Bitmap", rb_cObject); rb_define_method(Bitmap, "save_jpeg", image_save_jpeg, 2); + rb_define_method(Bitmap, "save_png", image_save_png, 1); + rb_define_method(Bitmap, "width", image_width, 0); + rb_define_method(Bitmap, "height", image_height, 0); + rb_define_method(Bitmap, "rescale", image_rescale, 2); Glyph = rb_define_class_under(GFX, "Glyph", rb_cObject); rb_define_method(Glyph, "polygon", glyph_polygon, 0); -- 1.7.10.4