diff --git a/io_scene_3ds/export_3ds.py b/io_scene_3ds/export_3ds.py
index 162e30de82f81bae895966e88e34e0974a637345..bf7bd9909149841038a1edda11135d649b12a87b 100644
--- a/io_scene_3ds/export_3ds.py
+++ b/io_scene_3ds/export_3ds.py
@@ -893,6 +893,7 @@ def save(operator, context, filepath="",
 
     import bpy
     import time
+    import io_utils
     from io_utils import create_derived_objects, free_derived_objects
 
     '''Save the Blender scene to a 3ds file.'''
@@ -901,8 +902,6 @@ def save(operator, context, filepath="",
     time1 = time.clock()
 #	Blender.Window.WaitCursor(1)
 
-    sce = context.scene
-
     if bpy.ops.object.mode_set.poll():
         bpy.ops.object.mode_set(mode='OBJECT')
 
@@ -921,15 +920,11 @@ def save(operator, context, filepath="",
     kfdata = make_kfdata()
     '''
 
-    # Get all the supported objects selected in this scene:
-    # ob_sel= list(sce.objects.context)
-    # mesh_objects = [ (ob, me) for ob in ob_sel   for me in (BPyMesh.getMeshFromObject(ob, None, True, False, sce),) if me ]
-    # empty_objects = [ ob for ob in ob_sel if ob.type == 'Empty' ]
-
     # Make a list of all materials used in the selected meshes (use a dictionary,
     # each material is added once):
     materialDict = {}
     mesh_objects = []
+
     scene = context.scene
 
     if use_selection:
diff --git a/io_scene_fbx/__init__.py b/io_scene_fbx/__init__.py
index 191f5824fdc80af82ef6be48c1eab8a776335131..54433a6506b31767ddb64d7332607601ea5aac88 100644
--- a/io_scene_fbx/__init__.py
+++ b/io_scene_fbx/__init__.py
@@ -41,6 +41,7 @@ if "bpy" in locals():
 
 import bpy
 from bpy.props import StringProperty, BoolProperty, FloatProperty, EnumProperty
+import io_utils
 from io_utils import ExportHelper
 
 
@@ -69,7 +70,6 @@ class ExportFBX(bpy.types.Operator, ExportHelper):
     EXP_MESH = BoolProperty(name="Meshes", description="Export mesh objects", default=True)
     EXP_MESH_APPLY_MOD = BoolProperty(name="Modifiers", description="Apply modifiers to mesh objects", default=True)
 #    EXP_MESH_HQ_NORMALS = BoolProperty(name="HQ Normals", description="Generate high quality normals", default=True)
-    EXP_IMAGE_COPY = BoolProperty(name="Copy Image Files", description="Copy image files to the destination path", default=False)
     # armature animation
     ANIM_ENABLE = BoolProperty(name="Enable Animation", description="Export keyframe animation", default=True)
     ANIM_OPTIMIZE = BoolProperty(name="Optimize Keyframes", description="Remove double keyframes", default=True)
@@ -87,6 +87,8 @@ class ExportFBX(bpy.types.Operator, ExportHelper):
     BATCH_OWN_DIR = BoolProperty(name="Own Dir", description="Create a dir for each exported file", default=True)
     use_metadata = BoolProperty(name="Use Metadata", default=True, options={'HIDDEN'})
 
+    path_mode = io_utils.path_reference_mode
+
     @property
     def check_extension(self):
         return self.batch_mode == 'OFF'
diff --git a/io_scene_fbx/export_fbx.py b/io_scene_fbx/export_fbx.py
index c4b03ddbd2ac6da7287ab44c1c66e747c366fb6a..8c533d82121a8b4b4d400361c3fc547514eb08b5 100644
--- a/io_scene_fbx/export_fbx.py
+++ b/io_scene_fbx/export_fbx.py
@@ -35,34 +35,6 @@ import bpy
 from mathutils import Vector, Matrix
 
 
-# XXX not used anymore, images are copied one at a time
-def copy_images(dest_dir, textures):
-    import shutil
-
-    if not dest_dir.endswith(os.sep):
-        dest_dir += os.sep
-
-    image_paths = set()
-    for tex in textures:
-        image_paths.add(bpy.path.abspath(tex.filepath))
-
-    # Now copy images
-    copyCount = 0
-    for image_path in image_paths:
-        if Blender.sys.exists(image_path):
-            # Make a name for the target path.
-            dest_image_path = dest_dir + image_path.split('\\')[-1].split('/')[-1]
-            if not Blender.sys.exists(dest_image_path):  # Image isnt already there
-                print("\tCopying %r > %r" % (image_path, dest_image_path))
-                try:
-                    shutil.copy(image_path, dest_image_path)
-                    copyCount += 1
-                except:
-                    print("\t\tWarning, file failed to copy, skipping.")
-
-    print('\tCopied %d images' % copyCount)
-
-
 # I guess FBX uses degrees instead of radians (Arystan).
 # Call this function just before writing to FBX.
 # 180 / math.pi == 57.295779513
@@ -157,25 +129,6 @@ def sane_takename(data):
 def sane_groupname(data):
     return sane_name(data, sane_name_mapping_group)
 
-# def derived_paths(fname_orig, basepath, FORCE_CWD=False):
-# 	'''
-# 	fname_orig - blender path, can be relative
-# 	basepath - fname_rel will be relative to this
-# 	FORCE_CWD - dont use the basepath, just add a ./ to the filepath.
-# 		use when we know the file will be in the basepath.
-# 	'''
-# 	fname = bpy.path.abspath(fname_orig)
-# # 	fname = Blender.sys.expandpath(fname_orig)
-# 	fname_strip = os.path.basename(fname)
-# # 	fname_strip = strip_path(fname)
-# 	if FORCE_CWD:
-# 		fname_rel = '.' + os.sep + fname_strip
-# 	else:
-# 		fname_rel = bpy.path.relpath(fname, basepath)
-# # 		fname_rel = Blender.sys.relpath(fname, basepath)
-# 	if fname_rel.startswith('//'): fname_rel = '.' + os.sep + fname_rel[2:]
-# 	return fname, fname_strip, fname_rel
-
 
 def mat4x4str(mat):
     return '%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f' % tuple([f for v in mat for f in v])
@@ -257,27 +210,28 @@ def save_single(operator, scene, filepath="",
         EXP_LAMP=True,
         EXP_CAMERA=True,
         EXP_EMPTY=True,
-        EXP_IMAGE_COPY=False,
         ANIM_ENABLE=True,
         ANIM_OPTIMIZE=True,
         ANIM_OPTIMIZE_PRECISSION=6,
         ANIM_ACTION_ALL=False,
         use_metadata=True,
+        path_mode='AUTO',
     ):
 
-    # testing
-    mtx_x90 = Matrix.Rotation(math.pi / 2.0, 3, 'X')  # used
+    import io_utils
+
+    mtx_x90 = Matrix.Rotation(math.pi / 2.0, 3, 'X')
     mtx4_z90 = Matrix.Rotation(math.pi / 2.0, 4, 'Z')
 
     if GLOBAL_MATRIX is None:
         GLOBAL_MATRIX = Matrix()
 
-    # end batch support
-
     # Use this for working out paths relative to the export location
-    basepath = os.path.dirname(filepath) or '.'
-    basepath += os.sep
-# 	basepath = Blender.sys.dirname(filepath)
+    base_src = os.path.dirname(bpy.data.filepath)
+    base_dst = os.path.dirname(filepath) 
+
+    # collect images to copy
+    copy_set = set()
 
     # ----------------------------------------------
     # storage classes
@@ -1139,22 +1093,6 @@ def save_single(operator, scene, filepath="",
         file.write('\n\t\t}')
         file.write('\n\t}')
 
-    def copy_image(image):
-        fn = bpy.path.abspath(image.filepath)
-        fn_strip = os.path.basename(fn)
-
-        if EXP_IMAGE_COPY:
-            rel = fn_strip
-            fn_abs_dest = os.path.join(basepath, fn_strip)
-            if not os.path.exists(fn_abs_dest):
-                shutil.copy(fn, fn_abs_dest)
-        elif bpy.path.is_subdir(fn, basepath):
-            rel = os.path.relpath(fn, basepath)
-        else:
-            rel = fn
-
-        return (rel, fn_strip)
-
     # tex is an Image (Arystan)
     def write_video(texname, tex):
         # Same as texture really!
@@ -1168,10 +1106,10 @@ def save_single(operator, scene, filepath="",
             Property: "Width", "int", "",0
             Property: "Height", "int", "",0''')
         if tex:
-            fname_rel, fname_strip = copy_image(tex)
-# 			fname, fname_strip, fname_rel = derived_paths(tex.filepath, basepath, EXP_IMAGE_COPY)
+            fname_rel = io_utils.path_reference(tex.filepath, base_src, base_dst, path_mode, "", copy_set)
+            fname_strip = os.path.basename(fname_rel)
         else:
-            fname = fname_strip = fname_rel = ''
+            fname_strip = fname_rel = ""
 
         file.write('\n\t\t\tProperty: "Path", "charptr", "", "%s"' % fname_strip)
 
@@ -1188,8 +1126,6 @@ def save_single(operator, scene, filepath="",
         UseMipMap: 0''')
 
         file.write('\n\t\tFilename: "%s"' % fname_strip)
-        if fname_strip:
-            fname_strip = '/' + fname_strip
         file.write('\n\t\tRelativeFilename: "%s"' % fname_rel)  # make relative
         file.write('\n\t}')
 
@@ -1229,10 +1165,10 @@ def save_single(operator, scene, filepath="",
         file.write('\n\t\tMedia: "Video::%s"' % texname)
 
         if tex:
-            fname_rel, fname_strip = copy_image(tex)
-# 			fname, fname_strip, fname_rel = derived_paths(tex.filepath, basepath, EXP_IMAGE_COPY)
+            fname_rel = io_utils.path_reference(tex.filepath, base_src, base_dst, path_mode, "", copy_set)
+            fname_strip = os.path.basename(fname_rel)
         else:
-            fname = fname_strip = fname_rel = ''
+            fname_strip = fname_rel = ""
 
         file.write('\n\t\tFileName: "%s"' % fname_strip)
         file.write('\n\t\tRelativeFilename: "%s"' % fname_rel)  # need some make relative command
@@ -2810,12 +2746,11 @@ Takes:  {''')
     ob_meshes[:] = []
     ob_null[:] = []
 
-    # copy images if enabled
-# 	if EXP_IMAGE_COPY:
-# # 		copy_images( basepath,  [ tex[1] for tex in textures if tex[1] != None ])
-# 		bpy.util.copy_images( [ tex[1] for tex in textures if tex[1] != None ], basepath)
     file.close()
 
+    # copy all collected files.
+    io_utils.path_reference_copy(copy_set)
+
     print('export finished in %.4f sec.' % (time.clock() - start_time))
     return {'FINISHED'}
 
diff --git a/io_scene_obj/__init__.py b/io_scene_obj/__init__.py
index 18685e5e30dc9649c62af694e3d3ede515e2dc36..d374bd6476909bce99aec4f4a071a58d1a6a0b2a 100644
--- a/io_scene_obj/__init__.py
+++ b/io_scene_obj/__init__.py
@@ -43,6 +43,7 @@ if "bpy" in locals():
 
 import bpy
 from bpy.props import BoolProperty, FloatProperty, StringProperty
+import io_utils
 from io_utils import ExportHelper, ImportHelper
 
 
@@ -102,7 +103,7 @@ class ExportOBJ(bpy.types.Operator, ExportHelper):
     use_hq_normals = BoolProperty(name="High Quality Normals", description="", default=True)
     use_uvs = BoolProperty(name="UVs", description="", default=True)
     use_materials = BoolProperty(name="Materials", description="", default=True)
-    copy_images = BoolProperty(name="Copy Images", description="", default=False)
+    # copy_images = BoolProperty(name="Copy Images", description="", default=False)
     use_triangles = BoolProperty(name="Triangulate", description="", default=False)
     use_vertex_groups = BoolProperty(name="Polygroups", description="", default=False)
     use_nurbs = BoolProperty(name="Nurbs", description="", default=False)
@@ -113,6 +114,8 @@ class ExportOBJ(bpy.types.Operator, ExportHelper):
     group_by_material = BoolProperty(name="Material Groups", description="", default=False)
     keep_vertex_order = BoolProperty(name="Keep Vertex Order", description="", default=False)
 
+    path_mode = io_utils.path_reference_mode
+
     def execute(self, context):
         from . import export_obj
         return export_obj.save(self, context, **self.as_keywords(ignore=("check_existing", "filter_glob")))
diff --git a/io_scene_obj/export_obj.py b/io_scene_obj/export_obj.py
index f5fed6a83310d86e67724abb133e06fd18e6b8c2..3b4737ae22a4220b9c39999bb72b3eac27086d73 100644
--- a/io_scene_obj/export_obj.py
+++ b/io_scene_obj/export_obj.py
@@ -24,6 +24,7 @@ import shutil
 
 import bpy
 import mathutils
+import io_utils
 
 
 def name_compat(name):
@@ -33,7 +34,7 @@ def name_compat(name):
         return name.replace(' ', '_')
 
 
-def write_mtl(scene, filepath, copy_images, mtl_dict):
+def write_mtl(scene, filepath, path_mode, copy_set, mtl_dict):
 
     world = scene.world
     if world:
@@ -41,6 +42,7 @@ def write_mtl(scene, filepath, copy_images, mtl_dict):
     else:
         worldAmb = 0.0, 0.0, 0.0
 
+    source_dir = bpy.data.filepath
     dest_dir = os.path.dirname(filepath)
 
     def copy_image(image):
@@ -106,9 +108,8 @@ def write_mtl(scene, filepath, copy_images, mtl_dict):
         # Write images!
         if img:  # We have an image on the face!
             # write relative image path
-            rel = copy_image(img)
+            rel = io_utils.path_reference(img.filepath, source_dir, dest_dir, path_mode, "", copy_set)
             file.write('map_Kd %s\n' % rel)  # Diffuse mapping image
-#           file.write('map_Kd %s\n' % img.filepath.split('\\')[-1].split('/')[-1]) # Diffuse mapping image
 
         elif mat:  # No face image. if we havea material search for MTex image.
             image_map = {}
@@ -133,7 +134,7 @@ def write_mtl(scene, filepath, copy_images, mtl_dict):
                             image_map["map_Ns"] = image
 
             for key, image in image_map.items():
-                filepath = copy_image(image)
+                filepath = io_utils.path_reference(image.filepath, source_dir, dest_dir, path_mode, "", copy_set)
                 file.write('%s %s\n' % (key, repr(filepath)[1:-1]))
 
         file.write('\n\n')
@@ -141,58 +142,6 @@ def write_mtl(scene, filepath, copy_images, mtl_dict):
     file.close()
 
 
-# XXX not used
-def copy_file(source, dest):
-    file = open(source, 'rb')
-    data = file.read()
-    file.close()
-
-    file = open(dest, 'wb')
-    file.write(data)
-    file.close()
-
-
-# XXX not used
-def copy_images(dest_dir):
-    if dest_dir[-1] != os.sep:
-        dest_dir += os.sep
-
-    # Get unique image names
-    uniqueImages = {}
-    for matname, mat, image in mtl_dict.values():  # Only use image name
-        # Get Texface images
-        if image:
-            uniqueImages[image] = image  # Should use sets here. wait until Python 2.4 is default.
-
-        # Get MTex images
-        if mat:
-            for mtex in mat.texture_slots:
-                if mtex and mtex.texture.type == 'IMAGE':
-                    image_tex = mtex.texture.image
-                    if image_tex:
-                        try:
-                            uniqueImages[image_tex] = image_tex
-                        except:
-                            pass
-
-    # Now copy images
-    copyCount = 0
-
-#   for bImage in uniqueImages.values():
-#       image_path = bpy.path.abspath(bImage.filepath)
-#       if bpy.sys.exists(image_path):
-#           # Make a name for the target path.
-#           dest_image_path = dest_dir + image_path.split('\\')[-1].split('/')[-1]
-#           if not bpy.utils.exists(dest_image_path): # Image isnt already there
-#               print('\tCopying "%s" > "%s"' % (image_path, dest_image_path))
-#               copy_file(image_path, dest_image_path)
-#               copyCount+=1
-
-#   paths= bpy.util.copy_images(uniqueImages.values(), dest_dir)
-
-    print('\tCopied %d images' % copyCount)
-
-
 def test_nurbs_compat(ob):
     if ob.type != 'CURVE':
         return False
@@ -272,21 +221,22 @@ def write_nurb(file, ob, ob_mat):
 
 
 def write_file(filepath, objects, scene,
-          EXPORT_TRI=False,
-          EXPORT_EDGES=False,
-          EXPORT_NORMALS=False,
-          EXPORT_NORMALS_HQ=False,
-          EXPORT_UV=True,
-          EXPORT_MTL=True,
-          EXPORT_COPY_IMAGES=False,
-          EXPORT_APPLY_MODIFIERS=True,
-          EXPORT_ROTX90=True,
-          EXPORT_BLEN_OBS=True,
-          EXPORT_GROUP_BY_OB=False,
-          EXPORT_GROUP_BY_MAT=False,
-          EXPORT_KEEP_VERT_ORDER=False,
-          EXPORT_POLYGROUPS=False,
-          EXPORT_CURVE_AS_NURBS=True):
+               EXPORT_TRI=False,
+               EXPORT_EDGES=False,
+               EXPORT_NORMALS=False,
+               EXPORT_NORMALS_HQ=False,
+               EXPORT_UV=True,
+               EXPORT_MTL=True,
+               EXPORT_APPLY_MODIFIERS=True,
+               EXPORT_ROTX90=True,
+               EXPORT_BLEN_OBS=True,
+               EXPORT_GROUP_BY_OB=False,
+               EXPORT_GROUP_BY_MAT=False,
+               EXPORT_KEEP_VERT_ORDER=False,
+               EXPORT_POLYGROUPS=False,
+               EXPORT_CURVE_AS_NURBS=True,
+               EXPORT_PATH_MODE='AUTO',
+               ):
     '''
     Basic write function. The context and options must be already set
     This can be accessed externaly
@@ -358,6 +308,8 @@ def write_file(filepath, objects, scene,
     # A Dict of Materials
     # (material.name, image.name):matname_imagename # matname_imagename has gaps removed.
     mtl_dict = {}
+    
+    copy_set = set()
 
     # Get all meshes
     for ob_main in objects:
@@ -694,17 +646,10 @@ def write_file(filepath, objects, scene,
 
     # Now we have all our materials, save them
     if EXPORT_MTL:
-        write_mtl(scene, mtlfilepath, EXPORT_COPY_IMAGES, mtl_dict)
-#   if EXPORT_COPY_IMAGES:
-#       dest_dir = os.path.basename(filepath)
-# #         dest_dir = filepath
-# #         # Remove chars until we are just the path.
-# #         while dest_dir and dest_dir[-1] not in '\\/':
-# #             dest_dir = dest_dir[:-1]
-#       if dest_dir:
-#           copy_images(dest_dir, mtl_dict)
-#       else:
-#           print('\tError: "%s" could not be used as a base for an image path.' % filepath)
+        write_mtl(scene, mtlfilepath, EXPORT_PATH_MODE, copy_set, mtl_dict)
+
+    # copy all collected files.
+    io_utils.path_reference_copy(copy_set)
 
     print("OBJ Export time: %.2f" % (time.clock() - time1))
 
@@ -716,7 +661,6 @@ def _write(context, filepath,
               EXPORT_NORMALS_HQ,  # not yet
               EXPORT_UV,  # ok
               EXPORT_MTL,
-              EXPORT_COPY_IMAGES,
               EXPORT_APPLY_MODIFIERS,  # ok
               EXPORT_ROTX90,  # wrong
               EXPORT_BLEN_OBS,
@@ -727,7 +671,9 @@ def _write(context, filepath,
               EXPORT_CURVE_AS_NURBS,
               EXPORT_SEL_ONLY,  # ok
               EXPORT_ALL_SCENES,  # XXX not working atm
-              EXPORT_ANIMATION):  # Not used
+              EXPORT_ANIMATION,
+              EXPORT_PATH_MODE,
+              ):  # Not used
 
     base_name, ext = os.path.splitext(filepath)
     context_name = [base_name, '', '', ext]  # Base name, scene name, frame number, extension
@@ -778,21 +724,22 @@ def _write(context, filepath,
             # erm... bit of a problem here, this can overwrite files when exporting frames. not too bad.
             # EXPORT THE FILE.
             write_file(full_path, objects, scene,
-                  EXPORT_TRI,
-                  EXPORT_EDGES,
-                  EXPORT_NORMALS,
-                  EXPORT_NORMALS_HQ,
-                  EXPORT_UV,
-                  EXPORT_MTL,
-                  EXPORT_COPY_IMAGES,
-                  EXPORT_APPLY_MODIFIERS,
-                  EXPORT_ROTX90,
-                  EXPORT_BLEN_OBS,
-                  EXPORT_GROUP_BY_OB,
-                  EXPORT_GROUP_BY_MAT,
-                  EXPORT_KEEP_VERT_ORDER,
-                  EXPORT_POLYGROUPS,
-                  EXPORT_CURVE_AS_NURBS)
+                       EXPORT_TRI,
+                       EXPORT_EDGES,
+                       EXPORT_NORMALS,
+                       EXPORT_NORMALS_HQ,
+                       EXPORT_UV,
+                       EXPORT_MTL,
+                       EXPORT_APPLY_MODIFIERS,
+                       EXPORT_ROTX90,
+                       EXPORT_BLEN_OBS,
+                       EXPORT_GROUP_BY_OB,
+                       EXPORT_GROUP_BY_MAT,
+                       EXPORT_KEEP_VERT_ORDER,
+                       EXPORT_POLYGROUPS,
+                       EXPORT_CURVE_AS_NURBS,
+                       EXPORT_PATH_MODE,
+                       )
 
         scene.frame_set(orig_frame, 0.0)
 
@@ -815,7 +762,6 @@ def save(operator, context, filepath="",
          use_hq_normals=False,
          use_uvs=True,
          use_materials=True,
-         copy_images=False,
          use_apply_modifiers=True,
          use_rotate_x90=True,
          use_blen_objects=True,
@@ -827,6 +773,7 @@ def save(operator, context, filepath="",
          use_selection=True,
          use_all_scenes=False,
          use_animation=False,
+         path_mode='AUTO'
          ):
 
     _write(context, filepath,
@@ -836,7 +783,6 @@ def save(operator, context, filepath="",
            EXPORT_NORMALS_HQ=use_hq_normals,
            EXPORT_UV=use_uvs,
            EXPORT_MTL=use_materials,
-           EXPORT_COPY_IMAGES=copy_images,
            EXPORT_APPLY_MODIFIERS=use_apply_modifiers,
            EXPORT_ROTX90=use_rotate_x90,
            EXPORT_BLEN_OBS=use_blen_objects,
@@ -848,6 +794,7 @@ def save(operator, context, filepath="",
            EXPORT_SEL_ONLY=use_selection,
            EXPORT_ALL_SCENES=use_all_scenes,
            EXPORT_ANIMATION=use_animation,
+           EXPORT_PATH_MODE=path_mode,
            )
 
     return {'FINISHED'}