diff --git src/simutrans/descriptor/reader/roadsign_reader.cc src/simutrans/descriptor/reader/roadsign_reader.cc
index c0933cea3..d3eb9e773 100644
--- src/simutrans/descriptor/reader/roadsign_reader.cc
+++ src/simutrans/descriptor/reader/roadsign_reader.cc
@@ -107,6 +107,11 @@ obj_desc_t *roadsign_reader_t::read_node(FILE *fp, obj_node_info_t &node)
 		dbg->fatal( "roadsign_reader_t::read_node()", "Cannot handle too new node version %i", version );
 	}
 
+	// the optional image lists (diagonal, front, drive-on-left) are additional
+	// nodes behind the cursor, found by their position; the child count says
+	// how many of them are there
+	desc->children = (uint8)node.nchildren;
+
 	if(  version<=3  &&  (  desc->is_choose_sign() ||  desc->is_private_way()  )  &&  desc->get_waytype() == road_wt  ) {
 		// do not shift these signs to the left for compatibility
 		desc->offset_left = 0;
diff --git src/simutrans/descriptor/roadsign_desc.h src/simutrans/descriptor/roadsign_desc.h
index f20c9ebf0..25b68cc61 100644
--- src/simutrans/descriptor/roadsign_desc.h
+++ src/simutrans/descriptor/roadsign_desc.h
@@ -22,6 +22,14 @@
  *  0   Name
  *  1   Copyright
  *  2   Image list
+ *  3   Cursor and icon
+ *  4   Diagonal image list (optional, see optional_children below)
+ *  5   Front image list (optional)
+ *  6   Front diagonal image list (optional)
+ *  7   Drive-on-left image list (optional)
+ *  8   Drive-on-left diagonal image list (optional)
+ *  9   Drive-on-left front image list (optional)
+ * 10   Drive-on-left front diagonal image list (optional)
  */
 class roadsign_desc_t : public obj_desc_transport_infrastructure_t {
 	friend class roadsign_reader_t;
@@ -33,6 +41,10 @@ private:
 
 	uint16 min_speed; // 0 = no min speed
 
+	// set from the number of children when loading, so it is not part of the
+	// node data and does not change the checksum of signs already published
+	uint8 children = 4;
+
 public:
 	enum types {
 		NONE                  = 0,
@@ -53,6 +65,84 @@ public:
 		return image != NULL ? image->get_id() : IMG_EMPTY;
 	}
 
+	// asks for the straight image, whatever the way below looks like
+	static const uint16 NO_DIAGONAL = 0xFFFF;
+
+	/*
+	 * The optional image lists behind the cursor child, found by their
+	 * position. makeobj writes them up to the last one the sign uses and
+	 * fills the skipped positions with empty lists, so a position never
+	 * changes its meaning. Missing or empty simply means: fall back.
+	 *
+	 * The left lists repeat the exact layout of their right counterparts;
+	 * the diagonal lists hold two entries per normal one, because a
+	 * direction needs a different image in each of the two bends it can
+	 * appear in, and the bend of the way picks between them.
+	 */
+	enum optional_children {
+		CHILD_DIAGONAL            =  4,
+		CHILD_FRONT               =  5,
+		CHILD_FRONT_DIAGONAL      =  6,
+		CHILD_LEFT                =  7,
+		CHILD_LEFT_DIAGONAL       =  8,
+		CHILD_LEFT_FRONT          =  9,
+		CHILD_LEFT_FRONT_DIAGONAL = 10
+	};
+
+private:
+	// one image of one optional list, or IMG_EMPTY when the list or the image is missing
+	image_id optional_image(uint8 child, uint16 index) const
+	{
+		if(  index == NO_DIAGONAL  ||  children <= child  ) {
+			return IMG_EMPTY;
+		}
+		image_t const* const image = get_child<image_list_t>(child)->get_image(index);
+		return image != NULL ? image->get_id() : IMG_EMPTY;
+	}
+
+public:
+	// most specific image first; every miss falls back one step, so an
+	// incomplete pak loses the specialisation and never the sign itself
+	image_id get_image_id(uint16 index, uint16 diagonal, bool left) const
+	{
+		if(  left  ) {
+			image_id img = optional_image( CHILD_LEFT_DIAGONAL, diagonal );
+			if(  img == IMG_EMPTY  ) {
+				img = optional_image( CHILD_LEFT, index );
+			}
+			if(  img != IMG_EMPTY  ) {
+				return img;
+			}
+		}
+		const image_id img = optional_image( CHILD_DIAGONAL, diagonal );
+		// falling back keeps the sign visible, and keeps its front/back order
+		// and its offsets exactly as they are without diagonals
+		return img != IMG_EMPTY ? img : get_image_id( (ribi_t::dir)index );
+	}
+
+	// the separate front list: when a pak provides it, image[] is the back
+	// image and frontimage[] the front one, instead of the position heuristics
+	image_id get_front_image_id(uint16 index, uint16 diagonal, bool left) const
+	{
+		if(  left  ) {
+			image_id img = optional_image( CHILD_LEFT_FRONT_DIAGONAL, diagonal );
+			if(  img == IMG_EMPTY  ) {
+				img = optional_image( CHILD_LEFT_FRONT, index );
+			}
+			if(  img != IMG_EMPTY  ) {
+				return img;
+			}
+		}
+		const image_id img = optional_image( CHILD_FRONT_DIAGONAL, diagonal );
+		return img != IMG_EMPTY ? img : optional_image( CHILD_FRONT, index );
+	}
+
+	bool has_diagonal_image() const { return children > CHILD_DIAGONAL; }
+	bool has_left_images()    const { return children > CHILD_LEFT; }
+	bool has_front_images(bool left) const { return children > (left ? CHILD_LEFT_FRONT : CHILD_FRONT); }
+
+	// only the normal list: this count decides whether a sign is a traffic light
+	// and whether it has electrified images, so the diagonals must stay out of it
 	uint16 get_count() const { return get_child<image_list_t>(2)->get_count(); }
 
 	skin_desc_t const* get_cursor() const { return get_child<skin_desc_t>(3); }
diff --git src/simutrans/descriptor/writer/roadsign_writer.cc src/simutrans/descriptor/writer/roadsign_writer.cc
index 55e5502c4..4069c24a6 100644
--- src/simutrans/descriptor/writer/roadsign_writer.cc
+++ src/simutrans/descriptor/writer/roadsign_writer.cc
@@ -19,8 +19,10 @@ static const char* private_sign_directions[] = {"ns", "ew"};
 static const char* traffic_light_directions[] = {"n", "s", "w", "e", "nw", "se", "sw", "ne"};
 static const char* general_sign_directions[] = {"n", "s", "w", "e"};
 
-// parse "image[direction][state]" syntax
-void parse_images_2d(slist_tpl<std::string>& keys, tabfileobj_t& obj, roadsign_desc_t::types flags)
+// parse "<name>[direction][state]" syntax for the states [state_begin, state_end).
+// When required is false, a completely absent first state means "this list is
+// not given" and is fine; a partially given state is an error either way
+void parse_images_2d(slist_tpl<std::string>& keys, tabfileobj_t& obj, roadsign_desc_t::types flags, const char* name, uint8 state_begin, uint8 state_end, bool required)
 {
 	const char** directions;
 	uint8 dir_cnt; // how many directions are there?
@@ -39,13 +41,17 @@ void parse_images_2d(slist_tpl<std::string>& keys, tabfileobj_t& obj, roadsign_d
 		dir_cnt = lengthof(general_sign_directions);
 	}
 
-	for(  uint8 state=0;  state<8;  state++  ) {
+	for(  uint8 state=state_begin;  state<state_end;  state++  ) {
 		for(  uint8 idx = 0;  idx < dir_cnt;  idx++  ) {
 			char buf[64];
-			sprintf(buf, "image[%s][%i]", directions[idx], state);
+			sprintf(buf, "%s[%s][%i]", name, directions[idx], state);
 			const char* img = obj.get(buf);
 			if(  !*img  ){
-				if(  state>(dir_cnt==2)  &&  idx==0  ) {
+				if(  !required  &&  state==state_begin  &&  idx==0  ) {
+					// the whole list is simply not there
+					return;
+				}
+				if(  state>state_begin+(dir_cnt==2)  &&  idx==0  ) {
 					// Assume all further state numbers are invalid.
 					return;
 				}
@@ -59,17 +65,36 @@ void parse_images_2d(slist_tpl<std::string>& keys, tabfileobj_t& obj, roadsign_d
 }
 
 
-// parse "image[number]" syntax
-void parse_images_numbered(slist_tpl<std::string>& keys, tabfileobj_t& obj)
+// parse "<name>[number]" syntax
+void parse_images_numbered(slist_tpl<std::string>& keys, tabfileobj_t& obj, const char* name)
 {
 	for (int i = 0; i < 32; i++) {
 		char buf[40];
-		sprintf(buf, "image[%i]", i);
+		sprintf(buf, "%s[%i]", name, i);
 		const char *str = obj.get(buf);
 		// make sure, there are always 4, 8, 12, ... images (for all directions)
 		if(  !*str  ) {
 			if(  i % 4  ) {
-				dbg->fatal("roadsign_writer", "image count is %d but must be multiple of 4!", i);
+				dbg->fatal("roadsign_writer", "%s count is %d but must be multiple of 4!", name, i);
+			}
+			break;
+		}
+		keys.append(str);
+	}
+}
+
+
+// parse "<name>[number][variant]" syntax
+void parse_images_numbered_variant(slist_tpl<std::string>& keys, tabfileobj_t& obj, const char* name, uint8 variant)
+{
+	for (int i = 0; i < 32; i++) {
+		char buf[48];
+		sprintf(buf, "%s[%i][%i]", name, i, variant);
+		const char *str = obj.get(buf);
+		// make sure, there are always 4, 8, 12, ... images (for all directions)
+		if(  !*str  ) {
+			if(  i % 4  ) {
+				dbg->fatal("roadsign_writer", "%s[..][%i] count is %d but must be multiple of 4!", name, variant, i);
 			}
 			break;
 		}
@@ -136,16 +161,60 @@ void roadsign_writer_t::write_obj(FILE* fp, obj_node_t& parent, tabfileobj_t& ob
 	// add the images
 	slist_tpl<std::string> keys;
 
+	// a signal uses the second index of image[..][..] for its states and a
+	// traffic light for its phases; only a plain sign can use it for the
+	// drive-on-left variant. The variant lists live in children of their own,
+	// so the count of the main list keeps meaning what it always meant - which
+	// is also what decides whether a sign is a traffic light
+	const bool plain_sign = (flags & (roadsign_desc_t::SIGN_SIGNAL|roadsign_desc_t::SIGN_PRE_SIGNAL|roadsign_desc_t::SIGN_PRIORITY_SIGNAL|roadsign_desc_t::SIGN_LONGBLOCK_SIGNAL|roadsign_desc_t::PRIVATE_ROAD)) == 0
+	                       &&  !*obj.get("image[ne][0]");
+
 	if(  *obj.get("image[0]")  ) {
 		// image[0] is defined.
 		// assume that images are defined in image[number] syntax.
-		parse_images_numbered(keys, obj);
+		parse_images_numbered(keys, obj, "image");
 	}
 	else {
 		// image[0] is not defined.
 		// assume that images are defined in image[direction][state] syntax.
-		parse_images_2d(keys, obj, flags);
+		parse_images_2d(keys, obj, flags, "image", 0, plain_sign ? 1 : 8, true);
 	}
+
+	// the optional lists, ordered as roadsign_desc_t::optional_children names
+	// them. The diagonal entries are places and not directions, two for each
+	// direction, so the [direction][state] syntax cannot name them and they
+	// are always numbered
+	slist_tpl<std::string> optional[7];
+	parse_images_numbered(optional[0], obj, "diagonal");                 // diagonal[n] ...
+	if(  optional[0].empty()  ) {
+		parse_images_numbered_variant(optional[0], obj, "diagonal", 0);  // ... or diagonal[n][0]
+	}
+	if(  *obj.get("frontimage[0]")  ) {
+		parse_images_numbered(optional[1], obj, "frontimage");
+	}
+	else {
+		parse_images_2d(optional[1], obj, flags, "frontimage", 0, 1, false);
+	}
+	parse_images_numbered_variant(optional[2], obj, "frontdiagonal", 0);
+	if(  optional[2].empty()  ) {
+		parse_images_numbered(optional[2], obj, "frontdiagonal");
+	}
+	if(  plain_sign  ) {
+		parse_images_2d(optional[3], obj, flags, "image", 1, 2, false);
+		parse_images_numbered_variant(optional[4], obj, "diagonal", 1);
+		parse_images_2d(optional[5], obj, flags, "frontimage", 1, 2, false);
+		parse_images_numbered_variant(optional[6], obj, "frontdiagonal", 1);
+	}
+
+	// any other length would silently shift the images instead of failing here
+	static const char* const optional_names[7] = { "diagonal", "frontimage", "frontdiagonal", "image[..][1]", "diagonal[..][1]", "frontimage[..][1]", "frontdiagonal[..][1]" };
+	for(  int j=0;  j<7;  j++  ) {
+		const uint32 want = (j&1) == 0 ? 2*keys.get_count() : keys.get_count();
+		if(  !optional[j].empty()  &&  optional[j].get_count() != want  ) {
+			dbg->fatal("roadsign_writer", "%i %s images given, but the sign needs %i!", optional[j].get_count(), optional_names[j], want);
+		}
+	}
+
 	imagelist_writer_t::instance()->write_obj(fp, node, keys);
 
 	// probably add some icons, if defined
@@ -154,9 +223,26 @@ void roadsign_writer_t::write_obj(FILE* fp, obj_node_t& parent, tabfileobj_t& ob
 	const char *c = obj.get("cursor"), *i=obj.get("icon");
 	cursorkeys.append(c);
 	cursorkeys.append(i);
-	if (*c || *i) {
+
+	int last_list = -1;
+	for(  int j=0;  j<7;  j++  ) {
+		if(  !optional[j].empty()  ) {
+			last_list = j;
+		}
+	}
+	if (*c || *i || last_list>=0) {
+		// when optional lists follow, this node has to be written even if it is
+		// empty: the lists are found by their position, and would take this one
+		// otherwise
 		cursorskin_writer_t::instance()->write_obj(fp, node, obj, cursorkeys);
 	}
 
+	// the optional lists, up to the last one this sign uses; the gaps in
+	// between are written as empty lists so that a position never changes its
+	// meaning. Last children, so that older versions of Simutrans ignore them
+	for(  int j=0;  j<=last_list;  j++  ) {
+		imagelist_writer_t::instance()->write_obj(fp, node, optional[j]);
+	}
+
 	node.check_and_write_header(fp);
 }
diff --git src/simutrans/obj/roadsign.cc src/simutrans/obj/roadsign.cc
index 161a3e43a..0b61740b7 100644
--- src/simutrans/obj/roadsign.cc
+++ src/simutrans/obj/roadsign.cc
@@ -236,6 +236,21 @@ void roadsign_t::info(cbuffer_t & buf) const
 }
 
 
+void roadsign_t::calc_diagonal_index(uint16 idx[4], ribi_t::ribi way_ribi, uint16 base)
+{
+	// the image list is ordered north, south, west, east
+	static const ribi_t::ribi order[4] = { ribi_t::north, ribi_t::south, ribi_t::west, ribi_t::east };
+	assert(ribi_t::is_bend(way_ribi));
+	// the lower ribi of the bend takes the first of its two images, and the bends are
+	// numbered with ribi/3-1, the same way the ways number their diagonals
+	const ribi_t::ribi low = way_ribi & (~way_ribi + 1);
+	const uint16 bend = base + 2*(way_ribi/3 - 1);
+	for(  uint8 i = 0;  i < 4;  i++  ) {
+		idx[i] = (way_ribi & order[i]) ? bend + (order[i]==low ? 0 : 1) : roadsign_desc_t::NO_DIAGONAL;
+	}
+}
+
+
 // could be still better aligned for drive_left settings ...
 void roadsign_t::calc_image()
 {
@@ -247,14 +262,28 @@ void roadsign_t::calc_image()
 		return;
 	}
 
+	// signs on a bend use the diagonal images. The bend comes from the unmasked ribi:
+	// a one way sign masks a direction away, and a single direction is not a bend
+	uint16 diag[4] = { roadsign_desc_t::NO_DIAGONAL, roadsign_desc_t::NO_DIAGONAL, roadsign_desc_t::NO_DIAGONAL, roadsign_desc_t::NO_DIAGONAL };
+	const weg_t *w = gr->get_weg(desc->get_wtyp()!=tram_wt ? desc->get_wtyp() : track_wt);
+	if(  w != NULL  &&  w->is_diagonal()  &&  desc->has_diagonal_image()  ) {
+		calc_diagonal_index( diag, w->get_ribi_unmasked(), 0 );
+	}
+
 	after_xoffset = 0;
 	after_yoffset = 0;
 	sint8 xoff = 0, yoff = 0;
-	// left offsets defined, and image-on-the-left activated
-	const bool left_offsets = desc->get_offset_left()  &&
+	// image-on-the-left activated for this sign's waytype
+	const bool traffic_left =
 	    (     (desc->get_wtyp()==road_wt  &&  welt->get_settings().is_drive_left()  )
 	      ||  (desc->get_wtyp()!=air_wt  &&  desc->get_wtyp()!=road_wt  &&  welt->get_settings().is_signals_left())
 	    );
+	// left offsets defined, and image-on-the-left activated
+	const bool left_offsets = desc->get_offset_left()  &&  traffic_left;
+	// use the drive-on-left variant lists when the pak has them: both variants
+	// live in the pak, because a pak is loaded before the savegame says which
+	// side its world drives on
+	const bool left_variant = traffic_left  &&  desc->has_left_images();
 
 	const slope_t::type full_hang = gr->get_weg_hang();
 	const sint8 hang_diff = slope_t::max_diff(full_hang);
@@ -321,38 +350,38 @@ void roadsign_t::calc_image()
 			const sint16 YOFF = desc->get_offset_left();
 
 			if(temp_dir&ribi_t::east) {
-				tmp_image = desc->get_image_id(3);
+				tmp_image = desc->get_image_id(3, diag[3], left_variant);
 				xoff += XOFF;
 				yoff += -YOFF;
 			}
 
 			if(temp_dir&ribi_t::north) {
 				if(tmp_image!=IMG_EMPTY) {
-					foreground_image = desc->get_image_id(0);
+					foreground_image = desc->get_image_id(0, diag[0], left_variant);
 					after_xoffset += -XOFF;
 					after_yoffset += -YOFF;
 				}
 				else {
-					tmp_image = desc->get_image_id(0);
+					tmp_image = desc->get_image_id(0, diag[0], left_variant);
 					xoff += -XOFF;
 					yoff += -YOFF;
 				}
 			}
 
 			if(temp_dir&ribi_t::west) {
-				foreground_image = desc->get_image_id(2);
+				foreground_image = desc->get_image_id(2, diag[2], left_variant);
 				after_xoffset += -XOFF;
 				after_yoffset += YOFF;
 			}
 
 			if(temp_dir&ribi_t::south) {
 				if(foreground_image!=IMG_EMPTY) {
-					tmp_image = desc->get_image_id(1);
+					tmp_image = desc->get_image_id(1, diag[1], left_variant);
 					xoff += XOFF;
 					yoff += YOFF;
 				}
 				else {
-					foreground_image = desc->get_image_id(1);
+					foreground_image = desc->get_image_id(1, diag[1], left_variant);
 					after_xoffset += XOFF;
 					after_yoffset += YOFF;
 				}
@@ -361,32 +390,42 @@ void roadsign_t::calc_image()
 		else {
 
 			if(temp_dir&ribi_t::east) {
-				foreground_image = desc->get_image_id(3);
+				foreground_image = desc->get_image_id(3, diag[3], left_variant);
 			}
 
 			if(temp_dir&ribi_t::north) {
 				if(foreground_image!=IMG_EMPTY) {
-					tmp_image = desc->get_image_id(0);
+					tmp_image = desc->get_image_id(0, diag[0], left_variant);
 				}
 				else {
-					foreground_image = desc->get_image_id(0);
+					foreground_image = desc->get_image_id(0, diag[0], left_variant);
 				}
 			}
 
 			if(temp_dir&ribi_t::west) {
-				tmp_image = desc->get_image_id(2);
+				tmp_image = desc->get_image_id(2, diag[2], left_variant);
 			}
 
 			if(temp_dir&ribi_t::south) {
 				if(tmp_image!=IMG_EMPTY) {
-					foreground_image = desc->get_image_id(1);
+					foreground_image = desc->get_image_id(1, diag[1], left_variant);
 				}
 				else {
-					tmp_image = desc->get_image_id(1);
+					tmp_image = desc->get_image_id(1, diag[1], left_variant);
 				}
 			}
 		}
 
+		// a pak that defines front images wants image[] drawn behind the
+		// vehicles and frontimage[] before them, instead of the position
+		// heuristics above. Only a sign showing a single direction has both
+		// slots free for that; two-direction signs keep the pairing above
+		if(  ribi_t::is_single(temp_dir)  &&  desc->has_front_images(left_variant)  ) {
+			const uint8 i = temp_dir==ribi_t::north ? 0 : temp_dir==ribi_t::south ? 1 : temp_dir==ribi_t::west ? 2 : 3;
+			tmp_image        = desc->get_image_id( i, diag[i], left_variant );
+			foreground_image = desc->get_front_image_id( i, diag[i], left_variant );
+		}
+
 		// some signs on roads must not have a background (but then they have only two rotations)
 		if(  desc->get_flags()&roadsign_desc_t::ONLY_BACKIMAGE  ) {
 			if(foreground_image!=IMG_EMPTY) {
diff --git src/simutrans/obj/roadsign.h src/simutrans/obj/roadsign.h
index 1f8ae1b92..dc0a886f6 100644
--- src/simutrans/obj/roadsign.h
+++ src/simutrans/obj/roadsign.h
@@ -39,6 +39,10 @@ protected:
 	uint8 automatic:1;
 	uint8 preview:1;
 
+	// diagonal image of each direction, ordered as the image list has them: north, south,
+	// west, east. base is where the row of this state and electrification starts
+	static void calc_diagonal_index(uint16 idx[4], ribi_t::ribi way_ribi, uint16 base);
+
 	/*
 	 * Many things go in these...
 	 *   Traffic lights -> intended usage
diff --git src/simutrans/obj/signal.cc src/simutrans/obj/signal.cc
index 776d41559..01ffa9f5d 100644
--- src/simutrans/obj/signal.cc
+++ src/simutrans/obj/signal.cc
@@ -47,11 +47,16 @@ void signal_t::calc_image()
 {
 	foreground_image = IMG_EMPTY;
 	image_id image = IMG_EMPTY;
+	uint16 diag[4] = { roadsign_desc_t::NO_DIAGONAL, roadsign_desc_t::NO_DIAGONAL, roadsign_desc_t::NO_DIAGONAL, roadsign_desc_t::NO_DIAGONAL };
 
 	after_xoffset = 0;
 	after_yoffset = 0;
 	sint8 xoff = 0, yoff = 0;
 	const bool left_swap = welt->get_settings().is_signals_left()  &&  desc->get_offset_left();
+	// use the drive-on-left variant lists when the pak has them and signals
+	// stand on the left; the lists repeat the layout of the normal one, so
+	// the state and electrification arithmetic below applies unchanged
+	const bool left_variant = welt->get_settings().is_signals_left()  &&  desc->has_left_images();
 
 	grund_t *gr = welt->lookup(get_pos());
 	if(gr) {
@@ -70,6 +75,12 @@ void signal_t::calc_image()
 				offset = (desc->is_pre_signal()  ||  desc->is_priority_signal()) ? 12 : 8;
 			}
 
+			// the bend comes from the unmasked ribi: a one way signal masks a direction away,
+			// and a single direction is not a bend. The diagonal rows are twice as long
+			if(  sch->is_diagonal()  &&  desc->has_diagonal_image()  ) {
+				calc_diagonal_index( diag, sch->get_ribi_unmasked(), state*8 + offset*2 );
+			}
+
 			// vertical offset of the signal positions
 			if(full_hang==slope_t::flat) {
 				yoff = -gr->get_weg_yoff();
@@ -108,38 +119,38 @@ void signal_t::calc_image()
 				const sint16 YOFF = desc->get_offset_left();
 
 				if(temp_dir&ribi_t::east) {
-					image = desc->get_image_id(3+state*4+offset);
+					image = desc->get_image_id(3+state*4+offset, diag[3], left_variant);
 					xoff += XOFF;
 					yoff += -YOFF;
 				}
 
 				if(temp_dir&ribi_t::north) {
 					if(image!=IMG_EMPTY) {
-						foreground_image = desc->get_image_id(0+state*4+offset);
+						foreground_image = desc->get_image_id(0+state*4+offset, diag[0], left_variant);
 						after_xoffset += -XOFF;
 						after_yoffset += -YOFF;
 					}
 					else {
-						image = desc->get_image_id(0+state*4+offset);
+						image = desc->get_image_id(0+state*4+offset, diag[0], left_variant);
 						xoff += -XOFF;
 						yoff += -YOFF;
 					}
 				}
 
 				if(temp_dir&ribi_t::west) {
-					foreground_image = desc->get_image_id(2+state*4+offset);
+					foreground_image = desc->get_image_id(2+state*4+offset, diag[2], left_variant);
 					after_xoffset += -XOFF;
 					after_yoffset += YOFF;
 				}
 
 				if(temp_dir&ribi_t::south) {
 					if(foreground_image!=IMG_EMPTY) {
-						image = desc->get_image_id(1+state*4+offset);
+						image = desc->get_image_id(1+state*4+offset, diag[1], left_variant);
 						xoff += XOFF;
 						yoff += YOFF;
 					}
 					else {
-						foreground_image = desc->get_image_id(1+state*4+offset);
+						foreground_image = desc->get_image_id(1+state*4+offset, diag[1], left_variant);
 						after_xoffset += XOFF;
 						after_yoffset += YOFF;
 					}
@@ -147,28 +158,28 @@ void signal_t::calc_image()
 			}
 			else {
 				if(temp_dir&ribi_t::east) {
-					foreground_image = desc->get_image_id(3+state*4+offset);
+					foreground_image = desc->get_image_id(3+state*4+offset, diag[3], left_variant);
 				}
 
 				if(temp_dir&ribi_t::north) {
 					if(foreground_image==IMG_EMPTY) {
-						foreground_image = desc->get_image_id(0+state*4+offset);
+						foreground_image = desc->get_image_id(0+state*4+offset, diag[0], left_variant);
 					}
 					else {
-						image = desc->get_image_id(0+state*4+offset);
+						image = desc->get_image_id(0+state*4+offset, diag[0], left_variant);
 					}
 				}
 
 				if(temp_dir&ribi_t::west) {
-					image = desc->get_image_id(2+state*4+offset);
+					image = desc->get_image_id(2+state*4+offset, diag[2], left_variant);
 				}
 
 				if(temp_dir&ribi_t::south) {
 					if(image==IMG_EMPTY) {
-						image = desc->get_image_id(1+state*4+offset);
+						image = desc->get_image_id(1+state*4+offset, diag[1], left_variant);
 					}
 					else {
-						foreground_image = desc->get_image_id(1+state*4+offset);
+						foreground_image = desc->get_image_id(1+state*4+offset, diag[1], left_variant);
 					}
 				}
 			}
