diff --git a/doc/release_notes/v1.4.0.rst b/doc/release_notes/v1.4.0.rst
index 89e8ed34a..ab11550e6 100644
--- a/doc/release_notes/v1.4.0.rst
+++ b/doc/release_notes/v1.4.0.rst
@@ -69,6 +69,8 @@ Enhancements
   (:issue:`452`)
 * JPEG 2000 (1.2.840.10008.1.2.4.91) transfer syntax is supported for data
   with bit depth > 8 with the Pillow pixel data handler
+* A warning has been added when attempting to save a dataset with compressed
+  transfer syntax but no encapsulation of the pixel data. (:issue:`1007`)
 
 Changes
 .......
diff --git a/pydicom/dataset.py b/pydicom/dataset.py
index c8e8698e0..9bb62bc29 100644
--- a/pydicom/dataset.py
+++ b/pydicom/dataset.py
@@ -15,13 +15,14 @@ Dataset (dict subclass)
             contains its own DataElements, and so on in a recursive manner.
 """
 
-import inspect  # for __dir__
+from bisect import bisect_left
 import io
+import inspect  # for __dir__
+from itertools import takewhile
 import json
 import os
 import os.path
-from bisect import bisect_left
-from itertools import takewhile
+import warnings
 
 import pydicom  # for dcmwrite
 import pydicom.charset
@@ -1758,6 +1759,22 @@ class Dataset(dict):
                 "set appropriately before saving.".format(
                     self.__class__.__name__))
 
+        # If compressed transfer syntax check that Pixel Data is encapsulated
+        try:
+            tsyntax = self.file_meta.TransferSyntaxUID
+            if not tsyntax.is_private and tsyntax.is_compressed:
+                # Check for Basic Offset Table item tag
+                # Must always be little endian - PS3.5 Annex A.4
+                assert self.PixelData[:4] == b'\xFE\xFF\x00\xE0'
+        except AttributeError:
+            pass
+        except AssertionError:
+            warnings.warn(
+                "The dataset uses a compressed Transfer Syntax UID but the "
+                "Pixel Data hasn't been encapsulated. See the "
+                "pydicom.encaps.encapsulate() function for more information"
+            )
+
         pydicom.dcmwrite(filename, self, write_like_original)
 
     def ensure_file_meta(self):

Warn when attempting to save unencapsulated compressed datasets
**Is your feature request related to a problem? Please describe.**
Another common gotcha with saving compressed pixel data is that it first needs to be encapsulated.

**Describe the solution you'd like**
I think we should add a simple check when saving that looks to see whether or not Pixel Data has been encapsulated when the transfer syntax is compressed. If not then the user should get a warning (because maybe that was their intention).

diff --git a/pydicom/tests/test_dataset.py b/pydicom/tests/test_dataset.py
index 19909325b..4513c020d 100644
--- a/pydicom/tests/test_dataset.py
+++ b/pydicom/tests/test_dataset.py
@@ -8,6 +8,7 @@ from pydicom import compat
 from pydicom.data import get_testdata_files
 from pydicom.dataelem import DataElement, RawDataElement
 from pydicom.dataset import Dataset, FileDataset, validate_file_meta
+from pydicom.encaps import encapsulate
 from pydicom import dcmread
 from pydicom.filebase import DicomBytesIO
 from pydicom.overlay_data_handlers import numpy_handler as NP_HANDLER
@@ -17,6 +18,7 @@ from pydicom.tag import Tag
 from pydicom.uid import (
     ImplicitVRLittleEndian,
     ExplicitVRBigEndian,
+    JPEGBaseline,
     PYDICOM_IMPLEMENTATION_UID
 )
 
@@ -1122,6 +1124,67 @@ class TestDataset(object):
         ds.file_meta.ImplementationClassUID = '1.4'
         ds.save_as(fp, write_like_original=False)
 
+    def test_save_as_compressed_no_encaps(self):
+        """Test saving a compressed dataset with no encapsulation."""
+        fp = DicomBytesIO()
+        ds = Dataset()
+        ds.is_little_endian = True
+        ds.is_implicit_VR = False
+        ds.file_meta = Dataset()
+        ds.file_meta.TransferSyntaxUID = JPEGBaseline
+        ds.PixelData = b'\x00\x01\x02\x03\x04\x05\x06'
+        ds['PixelData'].VR = 'OB'
+        msg = (
+            r"The dataset uses a compressed Transfer Syntax UID but the "
+            r"Pixel Data hasn't been encapsulated"
+        )
+        with pytest.warns(UserWarning, match=msg):
+            ds.save_as(fp)
+
+    def test_save_as_compressed_encaps(self):
+        """Test saving a compressed dataset with encapsulation."""
+        fp = DicomBytesIO()
+        ds = Dataset()
+        ds.is_little_endian = True
+        ds.is_implicit_VR = False
+        ds.file_meta = Dataset()
+        ds.file_meta.TransferSyntaxUID = JPEGBaseline
+        ds.PixelData = encapsulate([b'\x00\x01\x02\x03\x04\x05\x06'])
+        ds['PixelData'].VR = 'OB'
+        ds.save_as(fp)
+
+    def test_save_as_no_pixel_data(self):
+        """Test saving with no Pixel Data."""
+        fp = DicomBytesIO()
+        ds = Dataset()
+        ds.is_little_endian = True
+        ds.is_implicit_VR = False
+        ds.file_meta = Dataset()
+        ds.file_meta.TransferSyntaxUID = JPEGBaseline
+        ds.save_as(fp)
+
+    def test_save_as_no_file_meta(self):
+        """Test saving with no Transfer Syntax or file_meta."""
+        fp = DicomBytesIO()
+        ds = Dataset()
+        ds.is_little_endian = True
+        ds.is_implicit_VR = False
+        ds.file_meta = Dataset()
+        ds.save_as(fp)
+
+        del ds.file_meta
+        ds.save_as(fp)
+
+    def test_save_as_private_transfer_syntax(self):
+        """Test saving with a private transfer syntax."""
+        fp = DicomBytesIO()
+        ds = Dataset()
+        ds.is_little_endian = True
+        ds.is_implicit_VR = False
+        ds.file_meta = Dataset()
+        ds.file_meta.TransferSyntaxUID = '1.2.3.4.5.6'
+        ds.save_as(fp)
+
     def test_with(self):
         """Test Dataset.__enter__ and __exit__."""
         test_file = get_testdata_files('CT_small.dcm')[0]

pip install -e .[dev]
parse_log_pytest
pytest
numpy>=1.16.0 pytest pytest-cov
apt-get update apt-get install -y gcc
3.7
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs @ file:///croot/attrs_1668696182826/work
certifi @ file:///croot/certifi_1671487769961/work/certifi
coverage==7.2.7
flit_core @ file:///opt/conda/conda-bld/flit-core_1644941570762/work/source/flit_core
importlib-metadata @ file:///tmp/build/80754af9/importlib-metadata_1648562407465/work
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
numpy==1.21.6
packaging @ file:///croot/packaging_1671697413597/work
pluggy @ file:///tmp/build/80754af9/pluggy_1648042572264/work
py @ file:///opt/conda/conda-bld/py_1644396412707/work
-e git+https://github.com/pydicom/pydicom.git@73cffe3151915b53a18b521656680d819e7e1a18#egg=pydicom
pytest==7.1.2
pytest-cov==4.1.0
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work
typing_extensions @ file:///croot/typing_extensions_1669924550328/work
zipp @ file:///croot/zipp_1672387121353/work

name: pydicom
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - attrs=22.1.0=py37h06a4308_0
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - flit-core=3.6.0=pyhd3eb1b0_0
  - importlib-metadata=4.11.3=py37h06a4308_0
  - importlib_metadata=4.11.3=hd3eb1b0_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - packaging=22.0=py37h06a4308_0
  - pip=22.3.1=py37h06a4308_0
  - pluggy=1.0.0=py37h06a4308_1
  - py=1.11.0=pyhd3eb1b0_0
  - pytest=7.1.2=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tomli=2.0.1=py37h06a4308_0
  - typing_extensions=4.4.0=py37h06a4308_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zipp=3.11.0=py37h06a4308_0
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - coverage==7.2.7
      - numpy==1.21.6
      - pytest-cov==4.1.0
prefix: /opt/conda/envs/pydicom

pydicom/tests/test_dataset.py::TestDataset::test_save_as_compressed_no_encaps
pydicom/tests/test_dataset.py::TestDataset::test_attribute_error_in_property pydicom/tests/test_dataset.py::TestDataset::test_for_stray_raw_data_element pydicom/tests/test_dataset.py::TestDataset::test_attribute_error_in_property_correct_debug pydicom/tests/test_dataset.py::TestDataset::test_tag_exception_print pydicom/tests/test_dataset.py::TestDataset::test_tag_exception_walk pydicom/tests/test_dataset.py::TestDataset::test_set_new_data_element_by_name pydicom/tests/test_dataset.py::TestDataset::test_set_existing_data_element_by_name pydicom/tests/test_dataset.py::TestDataset::test_set_non_dicom pydicom/tests/test_dataset.py::TestDataset::test_membership pydicom/tests/test_dataset.py::TestDataset::test_contains pydicom/tests/test_dataset.py::TestDataset::test_clear pydicom/tests/test_dataset.py::TestDataset::test_pop pydicom/tests/test_dataset.py::TestDataset::test_pop_using_tuple pydicom/tests/test_dataset.py::TestDataset::test_pop_using_keyword pydicom/tests/test_dataset.py::TestDataset::test_popitem pydicom/tests/test_dataset.py::TestDataset::test_setdefault pydicom/tests/test_dataset.py::TestDataset::test_setdefault_tuple pydicom/tests/test_dataset.py::TestDataset::test_setdefault_use_value pydicom/tests/test_dataset.py::TestDataset::test_setdefault_keyword pydicom/tests/test_dataset.py::TestDataset::test_get_exists1 pydicom/tests/test_dataset.py::TestDataset::test_get_exists2 pydicom/tests/test_dataset.py::TestDataset::test_get_exists3 pydicom/tests/test_dataset.py::TestDataset::test_get_exists4 pydicom/tests/test_dataset.py::TestDataset::test_get_default1 pydicom/tests/test_dataset.py::TestDataset::test_get_default2 pydicom/tests/test_dataset.py::TestDataset::test_get_default3 pydicom/tests/test_dataset.py::TestDataset::test_get_default4 pydicom/tests/test_dataset.py::TestDataset::test_get_raises pydicom/tests/test_dataset.py::TestDataset::test_get_from_raw pydicom/tests/test_dataset.py::TestDataset::test__setitem__ pydicom/tests/test_dataset.py::TestDataset::test_matching_tags pydicom/tests/test_dataset.py::TestDataset::test_named_member_updated pydicom/tests/test_dataset.py::TestDataset::test_update pydicom/tests/test_dataset.py::TestDataset::test_dir_subclass pydicom/tests/test_dataset.py::TestDataset::test_dir pydicom/tests/test_dataset.py::TestDataset::test_dir_filter pydicom/tests/test_dataset.py::TestDataset::test_delete_dicom_attr pydicom/tests/test_dataset.py::TestDataset::test_delete_dicom_command_group_length pydicom/tests/test_dataset.py::TestDataset::test_delete_other_attr pydicom/tests/test_dataset.py::TestDataset::test_delete_dicom_attr_we_dont_have pydicom/tests/test_dataset.py::TestDataset::test_delete_item_long pydicom/tests/test_dataset.py::TestDataset::test_delete_item_tuple pydicom/tests/test_dataset.py::TestDataset::test_delete_non_existing_item pydicom/tests/test_dataset.py::TestDataset::test_equality_no_sequence pydicom/tests/test_dataset.py::TestDataset::test_equality_private pydicom/tests/test_dataset.py::TestDataset::test_equality_sequence pydicom/tests/test_dataset.py::TestDataset::test_equality_not_dataset pydicom/tests/test_dataset.py::TestDataset::test_equality_unknown pydicom/tests/test_dataset.py::TestDataset::test_equality_inheritance pydicom/tests/test_dataset.py::TestDataset::test_equality_elements pydicom/tests/test_dataset.py::TestDataset::test_inequality pydicom/tests/test_dataset.py::TestDataset::test_hash pydicom/tests/test_dataset.py::TestDataset::test_property pydicom/tests/test_dataset.py::TestDataset::test_add_repeater_elem_by_keyword pydicom/tests/test_dataset.py::TestDataset::test_setitem_slice_raises pydicom/tests/test_dataset.py::TestDataset::test_getitem_slice_raises pydicom/tests/test_dataset.py::TestDataset::test_empty_slice pydicom/tests/test_dataset.py::TestDataset::test_getitem_slice pydicom/tests/test_dataset.py::TestDataset::test_getitem_slice_ffff pydicom/tests/test_dataset.py::TestDataset::test_delitem_slice pydicom/tests/test_dataset.py::TestDataset::test_group_dataset pydicom/tests/test_dataset.py::TestDataset::test_get_item pydicom/tests/test_dataset.py::TestDataset::test_get_item_slice pydicom/tests/test_dataset.py::TestDataset::test_get_private_item pydicom/tests/test_dataset.py::TestDataset::test_private_block pydicom/tests/test_dataset.py::TestDataset::test_add_new_private_tag pydicom/tests/test_dataset.py::TestDataset::test_delete_private_tag pydicom/tests/test_dataset.py::TestDataset::test_private_creators pydicom/tests/test_dataset.py::TestDataset::test_is_original_encoding pydicom/tests/test_dataset.py::TestDataset::test_remove_private_tags pydicom/tests/test_dataset.py::TestDataset::test_data_element pydicom/tests/test_dataset.py::TestDataset::test_iterall pydicom/tests/test_dataset.py::TestDataset::test_save_as pydicom/tests/test_dataset.py::TestDataset::test_save_as_compressed_encaps pydicom/tests/test_dataset.py::TestDataset::test_save_as_no_pixel_data pydicom/tests/test_dataset.py::TestDataset::test_save_as_no_file_meta pydicom/tests/test_dataset.py::TestDataset::test_save_as_private_transfer_syntax pydicom/tests/test_dataset.py::TestDataset::test_with pydicom/tests/test_dataset.py::TestDataset::test_exit_exception pydicom/tests/test_dataset.py::TestDataset::test_pixel_array_already_have pydicom/tests/test_dataset.py::TestDataset::test_pixel_array_id_changed pydicom/tests/test_dataset.py::TestDataset::test_pixel_array_unknown_syntax pydicom/tests/test_dataset.py::TestDataset::test_formatted_lines pydicom/tests/test_dataset.py::TestDataset::test_formatted_lines_known_uid pydicom/tests/test_dataset.py::TestDataset::test_set_convert_private_elem_from_raw pydicom/tests/test_dataset.py::TestDataset::test_top pydicom/tests/test_dataset.py::TestDataset::test_trait_names pydicom/tests/test_dataset.py::TestDataset::test_walk pydicom/tests/test_dataset.py::TestDataset::test_update_with_dataset pydicom/tests/test_dataset.py::TestDatasetElements::test_sequence_assignment pydicom/tests/test_dataset.py::TestDatasetElements::test_ensure_file_meta pydicom/tests/test_dataset.py::TestDatasetElements::test_fix_meta_info pydicom/tests/test_dataset.py::TestDatasetElements::test_validate_and_correct_file_meta pydicom/tests/test_dataset.py::TestFileDataset::test_pickle pydicom/tests/test_dataset.py::TestFileDataset::test_pickle_modified pydicom/tests/test_dataset.py::TestFileDataset::test_equality_file_meta pydicom/tests/test_dataset.py::TestFileDataset::test_creation_with_container pydicom/tests/test_dataset.py::TestFileDataset::test_works_as_expected_within_numpy_array pydicom/tests/test_dataset.py::TestFileDataset::test_dataset_overrides_all_dict_attributes pydicom/tests/test_dataset.py::TestDatasetOverlayArray::test_no_possible pydicom/tests/test_dataset.py::TestDatasetOverlayArray::test_possible_not_available pydicom/tests/test_dataset.py::TestDatasetOverlayArray::test_possible_available pydicom/tests/test_dataset.py::TestDatasetOverlayArray::test_handler_raises
doc/release_notes/v1.4.0.rst pydicom/dataset.py
doc/release_notes/v1.4.0.rst pydicom/dataset.py