diff --git a/CHANGES.rst b/CHANGES.rst
index d99a6190be..88eee77a6e 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -10,6 +10,8 @@ Cubeviz
 Imviz
 ^^^^^
 
+- New Simple Image Rotation plugin to rotate the axes of images. [#1551]
+
 Mosviz
 ^^^^^^
 
diff --git a/docs/imviz/plugins.rst b/docs/imviz/plugins.rst
index e0da639237..fa0cd496fd 100644
--- a/docs/imviz/plugins.rst
+++ b/docs/imviz/plugins.rst
@@ -97,6 +97,26 @@ data label, the X and Y directions, and the zoom box.
 When you have multiple viewers created in Imviz, use the Viewer dropdown menu
 to change the active viewer that it tracks.
 
+.. _rotate-image-simple:
+
+Simple Image Rotation
+=====================
+
+.. warning::
+
+    Distortion is ignored, so using this plugin on distorted data is
+    not recommended.
+
+.. note::
+
+    Zoom box in :ref:`imviz-compass` will not show when rotation mode is on.
+
+This plugins rotates image(s) by the given angle.
+You can select viewer but that option only shows when applicable.
+You can enter the desired rotation angle in degrees clockwise.
+This angle is absolute, i.e., relative to original image orientation, not the current rotation.
+Click on the :guilabel:`ROTATE` button to finalize.
+
 .. _line-profile-xy:
 
 Line Profiles
diff --git a/docs/reference/api.rst b/docs/reference/api.rst
index d36b463266..4d8743973c 100644
--- a/docs/reference/api.rst
+++ b/docs/reference/api.rst
@@ -126,6 +126,9 @@ Plugins
 .. automodapi:: jdaviz.configs.imviz.plugins.links_control.links_control
    :no-inheritance-diagram:
 
+.. automodapi:: jdaviz.configs.imviz.plugins.rotate_image.rotate_image
+   :no-inheritance-diagram:
+
 .. automodapi:: jdaviz.configs.mosviz.plugins.row_lock.row_lock
    :no-inheritance-diagram:
 
diff --git a/jdaviz/app.py b/jdaviz/app.py
index de4fce3005..a3d1377384 100644
--- a/jdaviz/app.py
+++ b/jdaviz/app.py
@@ -1118,7 +1118,7 @@ def _viewer_by_reference(self, reference):
 
         Returns
         -------
-        `~glue_jupyter.bqplot.common.BqplotBaseView`
+        viewer : `~glue_jupyter.bqplot.common.BqplotBaseView`
             The viewer class instance.
         """
         viewer_item = self._viewer_item_by_reference(reference)
diff --git a/jdaviz/configs/imviz/imviz.yaml b/jdaviz/configs/imviz/imviz.yaml
index b95852648e..755d86b571 100644
--- a/jdaviz/configs/imviz/imviz.yaml
+++ b/jdaviz/configs/imviz/imviz.yaml
@@ -23,6 +23,7 @@ tray:
   - g-subset-plugin
   - imviz-links-control
   - imviz-compass
+  - imviz-rotate-image
   - imviz-line-profile-xy
   - imviz-aper-phot-simple
   - imviz-catalogs
diff --git a/jdaviz/configs/imviz/plugins/__init__.py b/jdaviz/configs/imviz/plugins/__init__.py
index 37c02ed392..c6a7f46336 100644
--- a/jdaviz/configs/imviz/plugins/__init__.py
+++ b/jdaviz/configs/imviz/plugins/__init__.py
@@ -5,6 +5,7 @@
 from .coords_info import *  # noqa
 from .links_control import *  # noqa
 from .compass import *  # noqa
+from .rotate_image import *  # noqa
 from .aper_phot_simple import *  # noqa
 from .line_profile_xy import *  # noqa
-from .catalogs import *  # noqa
\ No newline at end of file
+from .catalogs import *  # noqa
diff --git a/jdaviz/configs/imviz/plugins/rotate_image/__init__.py b/jdaviz/configs/imviz/plugins/rotate_image/__init__.py
new file mode 100644
index 0000000000..11ffcbe2ff
--- /dev/null
+++ b/jdaviz/configs/imviz/plugins/rotate_image/__init__.py
@@ -0,0 +1 @@
+from .rotate_image import *  # noqa
diff --git a/jdaviz/configs/imviz/plugins/rotate_image/rotate_image.py b/jdaviz/configs/imviz/plugins/rotate_image/rotate_image.py
new file mode 100644
index 0000000000..c930319922
--- /dev/null
+++ b/jdaviz/configs/imviz/plugins/rotate_image/rotate_image.py
@@ -0,0 +1,35 @@
+import math
+
+from traitlets import Any
+
+from jdaviz.core.registries import tray_registry
+from jdaviz.core.template_mixin import TemplateMixin, ViewerSelectMixin
+
+
+@tray_registry('imviz-rotate-image', label="Simple Image Rotation")
+class RotateImageSimple(TemplateMixin, ViewerSelectMixin):
+    template_file = __file__, "rotate_image.vue"
+
+    angle = Any(0).tag(sync=True)
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        self._theta = 0  # degrees, clockwise
+
+    def vue_rotate_image(self, *args, **kwargs):
+        # We only grab the value here to avoid constantly updating as
+        # user is still entering or updating the value.
+        try:
+            self._theta = float(self.angle)
+        except Exception:
+            return
+
+        viewer = self.app._viewer_by_id(self.viewer_selected)
+
+        # Rotate selected viewer canvas.
+        # TODO: Translation still a bit broken if zoomed in.
+        viewer.state.rotation = math.radians(self._theta)
+
+        # TODO: Zoom box in Compass still broken, how to fix? If not, we need to disable it.
+        # Update Compass plugin.
+        viewer.on_limits_change()
diff --git a/jdaviz/configs/imviz/plugins/rotate_image/rotate_image.vue b/jdaviz/configs/imviz/plugins/rotate_image/rotate_image.vue
new file mode 100644
index 0000000000..20962c505b
--- /dev/null
+++ b/jdaviz/configs/imviz/plugins/rotate_image/rotate_image.vue
@@ -0,0 +1,30 @@
+<template>
+  <j-tray-plugin>
+    <v-row>
+      <j-docs-link :link="'https://jdaviz.readthedocs.io/en/'+vdocs+'/'+config+'/plugins.html#simple-image-rotation'">Rotate image.</j-docs-link>
+    </v-row>
+
+    <plugin-viewer-select
+      :items="viewer_items"
+      :selected.sync="viewer_selected"
+      label="Viewer"
+      hint="Select viewer."
+    />
+
+    <v-row>
+      <v-col>
+        <v-text-field
+          v-model="angle"
+          type="number"
+          label="Angle"
+          hint="Rotation angle in degrees clockwise"
+        ></v-text-field>
+      </v-col>
+    </v-row>
+
+    <v-row justify="end">
+      <v-btn color="primary" text @click="rotate_image">Rotate</v-btn>
+    </v-row>
+
+  </j-tray-plugin>
+</template>
diff --git a/jdaviz/configs/imviz/plugins/viewers.py b/jdaviz/configs/imviz/plugins/viewers.py
index f43dcf8adb..88f4644edc 100644
--- a/jdaviz/configs/imviz/plugins/viewers.py
+++ b/jdaviz/configs/imviz/plugins/viewers.py
@@ -209,7 +209,7 @@ def blink_once(self, reversed=False):
                     self.state.layers[ilayer].visible = False
 
                 # We can display the active data label in Compass plugin.
-                self.set_compass(self.state.layers[next_layer].layer)
+                self.set_compass(self.state.layers[next_layer].layer, transform=self.state._affine_pretransform._transform if self.state._affine_pretransform else None)
 
                 # Update line profile plots too.
                 if self.line_profile_xy is None:
@@ -228,7 +228,7 @@ def on_limits_change(self, *args):
             if self.compass is not None:
                 self.compass.clear_compass()
             return
-        self.set_compass(self.state.layers[i].layer)
+        self.set_compass(self.state.layers[i].layer, transform=self.state._affine_pretransform._transform if self.state._affine_pretransform else None)
 
     def _get_real_xy(self, image, x, y):
         """Return real (X, Y) position and status in case of dithering.
@@ -275,7 +275,7 @@ def _get_zoom_limits(self, image):
                                     (self.state.x_max, self.state.y_min)))
         return zoom_limits
 
-    def set_compass(self, image):
+    def set_compass(self, image, transform=None):
         """Update the Compass plugin with info from the given image Data object."""
         if self.compass is None:  # Maybe another viewer has it
             return
@@ -290,7 +290,7 @@ def set_compass(self, image):
         norm = ImageNormalize(vmin=vmin, vmax=vmax, stretch=LinearStretch())
         self.compass.draw_compass(image.label, wcs_utils.draw_compass_mpl(
             arr, orig_shape=image.shape, wcs=image.coords, show=False, zoom_limits=zoom_limits,
-            norm=norm))
+            norm=norm, transform=transform))
 
     def set_plot_axes(self):
         self.figure.axes[1].tick_format = None
diff --git a/jdaviz/configs/imviz/wcs_utils.py b/jdaviz/configs/imviz/wcs_utils.py
index 4d6444a68f..f3563fbf3d 100644
--- a/jdaviz/configs/imviz/wcs_utils.py
+++ b/jdaviz/configs/imviz/wcs_utils.py
@@ -164,7 +164,7 @@ def get_compass_info(image_wcs, image_shape, r_fac=0.4):
     return x, y, xn, yn, xe, ye, degn, dege, xflip
 
 
-def draw_compass_mpl(image, orig_shape=None, wcs=None, show=True, zoom_limits=None, **kwargs):
+def draw_compass_mpl(image, orig_shape=None, wcs=None, show=True, zoom_limits=None, transform=None, **kwargs):
     """Visualize the compass using Matplotlib.
 
     Parameters
@@ -203,8 +203,12 @@ def draw_compass_mpl(image, orig_shape=None, wcs=None, show=True, zoom_limits=No
         plt.ioff()
 
     fig, ax = plt.subplots()
+    if transform is not None:
+        transform += ax.transData
+    else:
+        transform = ax.transData
     ax.imshow(image, extent=[-0.5, orig_shape[1] - 0.5, -0.5, orig_shape[0] - 0.5],
-              origin='lower', cmap='gray', **kwargs)
+              origin='lower', cmap='gray', transform=transform, **kwargs)
 
     if wcs is not None:
         try: