Skip to content

Commit

Permalink
Add image support (dj2#8)
Browse files Browse the repository at this point in the history
Add support for decoding images in the RTF stream.
  • Loading branch information
nippysaurus authored and dj2 committed May 9, 2017
1 parent 88df30e commit bdc5d20
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 0 deletions.
26 changes: 26 additions & 0 deletions bin/rtf_parse
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

require 'ruby-rtf'
require 'pp'
require 'base64'

@prefix = ''
@suffix = ''
Expand Down Expand Up @@ -80,6 +81,28 @@ def format(str, section)
str << @prefix + section[:text].force_encoding('UTF-8') + @suffix
end

def process_image(section)
mods = section[:modifiers]
mime = ''
case mods[:picture_format]
when 'jpeg'
mime = 'image/jpg'
when 'png'
mime = 'image/png'
when 'bmp'
mime = 'image/bmp'
when 'wmf'
mime = 'image/x-wmf'
end
hex = section[:text].scan(/../).map(&:hex).pack('c*')
base64 = Base64.strict_encode64(hex)
width = 'auto'
width = mods[:picture_width] * (mods[:picture_scale_x] || 100) / 100 if mods[:picture_width]
height = 'auto'
height = mods[:picture_height] * (mods[:picture_scale_y] || 100) / 100 if mods[:picture_height]
"<img width='#{width}' height='#{height}' src=\"data:#{mime};base64,#{base64}\"/>\n"
end

doc = RubyRTF::Parser.new.parse(File.open(ARGV[0]).read)

STDERR.puts doc
Expand All @@ -103,6 +126,9 @@ doc.sections.each do |section|
end
str << "</table>\n"
next
elsif mods[:picture]
str << process_image(section)
next
end

format(str, section)
Expand Down
11 changes: 11 additions & 0 deletions lib/ruby-rtf/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,15 @@ def handle_control(name, val, src, current_pos)

@context_stack.pop
end
when :pict then add_section!(picture: true)
when :jpegblip then add_section!(picture_format:'jpeg')
when :pngblip then add_section!(picture_format:'png')
when *[:dibitmap, :wbitmap] then add_section!(picture_format:'bmp')
when *[:wmetafile, :pmmetafile] then add_section!(picture_format:'wmf')
when :pich then add_section!(picture_height: RubyRTF.twips_to_points(val))
when :picw then add_section!(picture_width: RubyRTF.twips_to_points(val))
when :picscalex then add_section!(picture_scale_x: val.to_i)
when :picscaley then add_section!(picture_scale_y: val.to_i)

else
unless @seen[name]
Expand Down Expand Up @@ -514,7 +523,9 @@ def force_section!(mods = {}, text = nil)
#
# @return [Nil]
def reset_current_section!
paragraph = current_section[:modifiers].has_key?(:paragraph)
current_section[:modifiers].clear
current_section[:modifiers][:paragraph] = true if paragraph
end

def current_context
Expand Down
47 changes: 47 additions & 0 deletions spec/parser_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,53 @@
section[2][:text].should == 'Goodbye, cruel world.'
end

context 'parses pictures' do
let(:src_bitmap) do
src = '{\rtf1 {\pict\wbitmap\picw7064\pich5292\picwgoal4005\pichgoal3000\picscalex111\picscaley109
ffd8ffe000104a4649460001010100b400b40000ffe1158a687474703a2f2f6e732e61646f62652e636f6d2f7861702f3}}'
end
let(:src_jpeg) do
src = '{\rtf1 {\pict\jpegblip\picw7064\pich5292\picwgoal4005\pichgoal3000\picscalex111\picscaley109
ffd8ffe000104a4649460001010100b400b40000ffe1158a687474703a2f2f6e732e61646f62652e636f6d2f7861702f3}}'
end

it 'should parse jpeg' do
section = parser.parse(src_jpeg).sections
section[0][:modifiers][:picture].should be_true
section[0][:modifiers][:picture_format].should == 'jpeg'
end

it 'should parse bmp' do
section = parser.parse(src_bitmap).sections
section[0][:modifiers][:picture].should be_true
section[0][:modifiers][:picture_format].should == 'bmp'
section = parser.parse(src_bitmap).sections
section[0][:modifiers][:picture].should be_true
section[0][:modifiers][:picture_format].should == 'bmp'
end

it 'should parse width' do
section = parser.parse(src_bitmap).sections
section[0][:modifiers][:picture_width].should == 7064 / 20.0
end

it 'should parse height' do
section = parser.parse(src_bitmap).sections
section[0][:modifiers][:picture_height].should == 5292 / 20.0
end

it 'should parse scale' do
section = parser.parse(src_bitmap).sections
section[0][:modifiers][:picture_scale_x].should == 111
section[0][:modifiers][:picture_scale_y].should == 109
end

it 'should parse picture data' do
section = parser.parse(src_bitmap).sections
section[0][:text].should == 'ffd8ffe000104a4649460001010100b400b40000ffe1158a687474703a2f2f6e732e61646f62652e636f6d2f7861702f3'
end
end

it 'clears ul with ul0' do
src = '{\rtf1 \ul\b Hello\b0\ul0 World}'
section = parser.parse(src).sections
Expand Down

0 comments on commit bdc5d20

Please sign in to comment.