code: # -*- coding:  utf-8 -*-
  """
  Test suite specifically targeting ICC profiles
  """
  
  # Standard library imports ...
  from datetime import datetime
  try:
      import importlib.resources as ir
  except ImportError:  # pragma:  no cover
      # before 3.7
      import importlib_resources as ir
  import struct
  import tempfile
  import unittest
  import warnings
  
  # Third party library imports
  import numpy as np
  
  # Local imports
  import glymur
  from glymur import Jp2k
  from glymur._iccprofile import _ICCProfile
  from glymur.jp2box import (
      ColourSpecificationBox, ContiguousCodestreamBox, FileTypeBox,
      ImageHeaderBox, JP2HeaderBox, JPEG2000SignatureBox, InvalidJp2kError
  )
  from glymur.core import SRGB
  from . import fixtures, data
  
  
  class TestColourSpecificationBox(fixtures.TestCommon):
      """Test suite for colr box instantiation."""
  
      def setUp(self):
          super(TestColourSpecificationBox, self).setUp()
  
          j2k = Jp2k(self.j2kfile)
          codestream = j2k.get_codestream()
          height = codestream.segment[1].ysiz
          width = codestream.segment[1].xsiz
          num_components = len(codestream.segment[1].xrsiz)
  
          self.jp2b = JPEG2000SignatureBox()
          self.ftyp = FileTypeBox()
          self.jp2h = JP2HeaderBox()
          self.jp2c = ContiguousCodestreamBox()
          self.ihdr = ImageHeaderBox(height=height, width=width,
                                     num_components=num_components)
  
          self.icc_profile = ir.read_binary(data, 'sgray.icc')
  
      def test_bad_method_printing(self):
          """
          SCENARIO:  An ICC profile is both too short and has an invalid method
          value.
  
          EXPECTED RESULT:  Warnings are issued.  Printing the string
          representation should not error out.
          """
          with ir.path(data, 'issue405.dat') as path:
              with path.open('rb') as f:
                  f.seek(8)
                  with warnings.catch_warnings():
                      # Lots of things wrong with this file.
                      warnings.simplefilter('ignore')
                      box = ColourSpecificationBox.parse(f, length=80, offset=0)
                      str(box)
  
      def test_colr_with_out_enum_cspace(self):
          """must supply an enumerated colorspace when writing"""
          j2k = Jp2k(self.j2kfile)
  
          boxes = [self.jp2b, self.ftyp, self.jp2h, self.jp2c]
          boxes[2].box = [self.ihdr, ColourSpecificationBox(colorspace=None)]
          with open(self.temp_jp2_filename, mode='wb') as tfile:
              with self.assertRaises(InvalidJp2kError):
                  j2k.wrap(tfile.name, boxes=boxes)
  
      def test_missing_colr_box(self):
          """jp2h must have a colr box"""
          j2k = Jp2k(self.j2kfile)
          boxes = [self.jp2b, self.ftyp, self.jp2h, self.jp2c]
          boxes[2].box = [self.ihdr]
          with open(self.temp_jp2_filename, mode='wb') as tfile:
              with self.assertRaises(InvalidJp2kError):
                  j2k.wrap(tfile.name, boxes=boxes)
  
      def test_bad_approx_jp2_field(self):
          """JP2 has requirements for approx field"""
          j2k = Jp2k(self.j2kfile)
          boxes = [self.jp2b, self.ftyp, self.jp2h, self.jp2c]
          colr = ColourSpecificationBox(colorspace=SRGB, approximation=1)
          boxes[2].box = [self.ihdr, colr]
          with open(self.temp_jp2_filename, mode='wb') as tfile:
              with self.assertRaises(InvalidJp2kError):
                  j2k.wrap(tfile.name, boxes=boxes)
  
      def test_default_colr(self):
          """basic colr instantiation"""
          colr = ColourSpecificationBox(colorspace=SRGB)
          self.assertEqual(colr.method, glymur.core.ENUMERATED_COLORSPACE)
          self.assertEqual(colr.precedence, 0)
          self.assertEqual(colr.approximation, 0)
          self.assertEqual(colr.colorspace, SRGB)
          self.assertIsNone(colr.icc_profile)
  
      def test_icc_profile(self):
          """basic colr box with ICC profile"""
          colr = ColourSpecificationBox(icc_profile=self.icc_profile)
          self.assertEqual(colr.method, glymur.core.ENUMERATED_COLORSPACE)
          self.assertEqual(colr.precedence, 0)
          self.assertEqual(colr.approximation, 0)
  
          icc_profile = _ICCProfile(colr.icc_profile)
          self.assertEqual(icc_profile.header['Version'], '2.1.0')
          self.assertEqual(icc_profile.header['Color Space'], 'gray')
          self.assertIsNone(icc_profile.header['Datetime'])
  
          # Only True for version4
          self.assertFalse('Profile Id' in icc_profile.header.keys())
  
      def test_colr_with_bad_color(self):
          """
          SCENARIO:  A colr box has an invalid colorspace.
  
          EXPECTED RESULT:  An InvalidJp2kError is raised when attempting to
          write the box.
          """
          with self.assertWarns(UserWarning):
              # A warning is issued due to the bad colorspace.
              colr = ColourSpecificationBox(colorspace=-1, approximation=0)
  
          with tempfile.TemporaryFile() as tfile:
              with self.assertRaises(InvalidJp2kError):
                  colr.write(tfile)
  
      def test_write_colr_with_bad_method(self):
          """
          SCENARIO:  A colr box has an invalid method value.
  
          EXPECTED RESULT:  InvalidJp2kError
          """
          with warnings.catch_warnings():
              warnings.simplefilter('ignore')
              colr = ColourSpecificationBox(colorspace=SRGB, method=5)
          with tempfile.TemporaryFile() as tfile:
              with self.assertRaises(InvalidJp2kError):
                  colr.write(tfile)
  
  
  class TestSuite(unittest.TestCase):
      """Test suite for ICC Profile code."""
  
      def setUp(self):
          self.buffer = ir.read_binary(data, 'sgray.icc')
  
      def test_bad_rendering_intent(self):
          """
          The rendering intent is not in the range 0-4.
  
          It should be classified as 'unknown'
          """
          intent = struct.pack('>I', 10)
          self.buffer = self.buffer[:64] + intent + self.buffer[68:]
  
          icc_profile = _ICCProfile(self.buffer)
          self.assertEqual(icc_profile.header['Rendering Intent'], 'unknown')
  
      def test_version4(self):
          """
          ICC profile is version 4
          """
          leadoff = struct.pack('>IIBB', 416, 0, 4, 0)
          self.buffer = leadoff + self.buffer[10:]
  
          icc_profile = _ICCProfile(self.buffer)
          self.assertEqual(icc_profile.header['Version'], '4.0.0')
          self.assertTrue('Profile Id' in icc_profile.header.keys())
  
      def test_icc_profile(self):
          """
          SCENARIO:  The ColourDefinitionBox has an ICC profile.
  
          EXPECTED RESULT:  Verify the ICC profile metadata.
          """
          with ir.path(data, 'text_GBR.jp2') as path:
              with self.assertWarns(UserWarning):
                  # The brand is wrong, this is JPX, not JP2.
                  j = Jp2k(path)
          box = j.box[3].box[1]
  
          self.assertEqual(box.icc_profile_header['Size'], 1328)
          self.assertEqual(box.icc_profile_header['Color Space'], 'RGB')
          self.assertEqual(box.icc_profile_header['Connection Space'], 'XYZ')
          self.assertEqual(box.icc_profile_header['Datetime'],
                           datetime(2009, 2, 25, 11, 26, 11))
          self.assertEqual(box.icc_profile_header['File Signature'], 'acsp')
          self.assertEqual(box.icc_profile_header['Platform'], 'APPL')
          self.assertEqual(box.icc_profile_header['Flags'],
                           'not embedded, can be used independently')
          self.assertEqual(box.icc_profile_header['Device Manufacturer'], 'appl')
          self.assertEqual(box.icc_profile_header['Device Model'], '')
          self.assertEqual(box.icc_profile_header['Device Attributes'],
                           ('reflective, glossy, positive media polarity, '
                            'color media'))
          self.assertEqual(box.icc_profile_header['Rendering Intent'],
                           'perceptual')
          np.testing.assert_almost_equal(box.icc_profile_header['Illuminant'],
                                         np.array([0.9642023, 1.0, 0.824905]),
                                         decimal=6)
          self.assertEqual(box.icc_profile_header['Creator'], 'appl')
  
apis: numpy.array