From 6cd33a48159e48d13945a02664a5b184996859f3 Mon Sep 17 00:00:00 2001 From: Toshi MARUYAMA Date: Mon, 14 Nov 2011 07:52:03 +0000 Subject: [PATCH] improve rmagick feature of rfpdf plugin for PDF inline images (#3261) Contributed by Jun NAITOH. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@7806 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- vendor/plugins/rfpdf/lib/core/rmagick.rb | 5 + vendor/plugins/rfpdf/lib/tcpdf.rb | 111 +++++++++++++++++------ 2 files changed, 89 insertions(+), 27 deletions(-) diff --git a/vendor/plugins/rfpdf/lib/core/rmagick.rb b/vendor/plugins/rfpdf/lib/core/rmagick.rb index 43e9fae0c..d561047ce 100644 --- a/vendor/plugins/rfpdf/lib/core/rmagick.rb +++ b/vendor/plugins/rfpdf/lib/core/rmagick.rb @@ -57,6 +57,11 @@ module RFPDF end out['bits'] = image.channel_depth + File.open( TCPDF.k_path_cache + File::basename(filename), 'w'){|f| + f.binmode + f.print image.to_blob + f.close + } out end diff --git a/vendor/plugins/rfpdf/lib/tcpdf.rb b/vendor/plugins/rfpdf/lib/tcpdf.rb index f41e96437..110f7d520 100755 --- a/vendor/plugins/rfpdf/lib/tcpdf.rb +++ b/vendor/plugins/rfpdf/lib/tcpdf.rb @@ -2049,17 +2049,27 @@ class TCPDF if (@images[file].nil?) #First use of image, get info if (type == '') - pos = file.rindex('.'); - if (pos == 0) + pos = File::basename(file).rindex('.'); + if (pos.nil? or pos == 0) Error('Image file has no extension and no type was specified: ' + file); end + pos = file.rindex('.'); type = file[pos+1..-1]; end type.downcase! if (type == 'jpg' or type == 'jpeg') info=parsejpg(file); - elsif (type == 'png') - info=parsepng(file); + elsif (type == 'png' or type == 'gif') + img = Magick::ImageList.new(file) + img.format = "PNG" # convert to PNG from gif + img.opacity = 0 # PNG alpha channel delete + File.open( @@k_path_cache + File::basename(file), 'w'){|f| + f.binmode + f.print img.to_blob + f.close + } + info=parsepng( @@k_path_cache + File::basename(file)); + File.delete( @@k_path_cache + File::basename(file)) else #Allow for additional formats mtd='parse' + type; @@ -2075,15 +2085,37 @@ class TCPDF end #Automatic width and height calculation if needed if ((w == 0) and (h == 0)) + rescale_x = (@w - @r_margin - x) / (info['w'] / (@img_scale * @k)) + rescale_x = 1 if rescale_x >= 1 + if (y + info['h'] * rescale_x / (@img_scale * @k) > @page_break_trigger and !@in_footer and AcceptPageBreak()) + #Automatic page break + if @pages[@page+1].nil? + ws = @ws; + if (ws > 0) + @ws = 0; + out('0 Tw'); + end + AddPage(@cur_orientation); + if (ws > 0) + @ws = ws; + out(sprintf('%.3f Tw', ws * @k)); + end + else + @page += 1; + end + y=@t_margin; + end + rescale_y = (@page_break_trigger - y) / (info['h'] / (@img_scale * @k)) + rescale_y = 1 if rescale_y >= 1 + rescale = rescale_y >= rescale_x ? rescale_x : rescale_y + #Put image at 72 dpi # 2004-06-14 :: Nicola Asuni, scale factor where added - w = info['w'] / (@img_scale * @k); - h = info['h'] / (@img_scale * @k); - end - if (w == 0) + w = info['w'] * rescale / (@img_scale * @k); + h = info['h'] * rescale / (@img_scale * @k); + elsif (w == 0) w = h * info['w'] / info['h']; - end - if (h == 0) + elsif (h == 0) h = w * info['h'] / info['w']; end out(sprintf('q %.2f 0 0 %.2f %.2f %.2f cm /I%d Do Q', w*@k, h*@k, x*@k, (@h-(y+h))*@k, info['i'])); @@ -2846,7 +2878,7 @@ class TCPDF if (a.empty?) Error('Missing or incorrect image file: ' + file); end - if (a[2]!='JPEG') + if (!a[2].nil? and a[2]!='JPEG') Error('Not a JPEG file: ' + file); end if (a['channels'].nil? or a['channels']==3) @@ -2859,9 +2891,12 @@ class TCPDF bpc=!a['bits'].nil? ? a['bits'] : 8; #Read whole file data=''; - open(file,'rb') do |f| + + open( @@k_path_cache + File::basename(file),'rb') do |f| data< a[0],'h' => a[1],'cs' => colspace,'bpc' => bpc,'f'=>'DCTDecode','data' => data} end @@ -2882,11 +2917,11 @@ class TCPDF end w=freadint(f); h=freadint(f); - bpc=f.read(1)[0]; + bpc=f.read(1).unpack('C')[0]; if (bpc>8) Error('16-bit depth not supported: ' + file); end - ct=f.read(1)[0]; + ct=f.read(1).unpack('C')[0]; if (ct==0) colspace='DeviceGray'; elsif (ct==2) @@ -2896,13 +2931,13 @@ class TCPDF else Error('Alpha channel not supported: ' + file); end - if (f.read(1)[0] != 0) + if (f.read(1).unpack('C')[0] != 0) Error('Unknown compression method: ' + file); end - if (f.read(1)[0]!=0) + if (f.read(1).unpack('C')[0] != 0) Error('Unknown filter method: ' + file); end - if (f.read(1)[0]!=0) + if (f.read(1).unpack('C')[0] != 0) Error('Interlacing not supported: ' + file); end f.read(4); @@ -2922,9 +2957,9 @@ class TCPDF #Read transparency info t=f.read( n); if (ct==0) - trns = t[1][0] + trns = t[1].unpack('C')[0] elsif (ct==2) - trns = t[[1][0], t[3][0], t[5][0]] + trns = t[[1].unpack('C')[0], t[3].unpack('C')[0], t[5].unpack('C')[0]] else pos=t.include?(0.chr); if (pos!=false) @@ -3765,6 +3800,14 @@ class TCPDF end end + # + # Convert to accessible file path + # @param string :attrname image file name + # + def getImageFilename( attrname ) + nil + end + # # Process opening tags. # @param string :tag tag name (in upcase) @@ -3878,10 +3921,17 @@ class TCPDF when 'img' if (!attrs['src'].nil?) - Write(@lasth, '!' + attrs['src'] + '!', '', fill); -=begin Comment out. Because not implement image output yet. - # replace relative path with real server path - attrs['src'] = attrs['src'].gsub(@@k_path_url_cache, @@k_path_cache); + # Only generates image include a pdf if RMagick is avalaible + unless Object.const_defined?(:Magick) + Write(@lasth, attrs['src'], '', fill); + return + end + file = getImageFilename(attrs['src']) + if (file.nil?) + Write(@lasth, attrs['src'], '', fill); + return + end + if (attrs['width'].nil?) attrs['width'] = 0; end @@ -3889,10 +3939,17 @@ class TCPDF attrs['height'] = 0; end - Image(attrs['src'], GetX(),GetY(), pixelsToMillimeters(attrs['width']), pixelsToMillimeters(attrs['height'])); - #SetX(@img_rb_x); - SetY(@img_rb_y); -=end + begin + Image(file, GetX(),GetY(), pixelsToMillimeters(attrs['width']), pixelsToMillimeters(attrs['height'])); + #SetX(@img_rb_x); + SetY(@img_rb_y); + rescue => err + logger.error "pdf: Image: error: #{err.message}" + Write(@lasth, attrs['src'], '', fill); + if File.file?( @@k_path_cache + File::basename(file)) + File.delete( @@k_path_cache + File::basename(file)) + end + end end when 'ul', 'ol'