def parse(self, filePath):
        self._file = open(filePath)
        seekTo(self._file, 0)
        first = getCharToOrd(self._file)
        marker = getCharToOrd(self._file)
        if (first != 0xff or marker != JPEG_SOI):
            assert False, "Not in JPEG format !!"

        while (marker):
            first = getCharToOrd(self._file)
            if first != 0xff or first < 0:
                break
            marker = getCharToOrd(self._file)
            log("%s-%s"%(hex(first), hex(marker)))
            length = getBytes2(self._file)
            curPos = nowAt(self._file)
            log("length= %d, curPos=%d"%(length,curPos))

            if marker in [JPEG_EOI, JPEG_SOS]:
                log("EOI or SOS ... exit parsing")
                break
            elif marker == JPEG_APP0:
                log("Enter", "[APP0]", "add")
                log("Leave", "[APP0]", "remove")
                pass # TBD
            elif marker == JPEG_APP1:
                log("Enter", "[APP1]", "add")
                header = getChar(self._file, 4)
                log("header = %s"%(header))
                if header.lower() == 'exif':
                    self.__parseAPP1(curPos+6, curPos, curPos+length-2)
                elif header.lower() == 'http':
                    seekTo(self._file, curPos)
                    xmpBuffer = getChar(self._file, length)
                    checkURL = "http://ns.adobe.com/xap/1.0/"
                    if xmpBuffer.startswith(checkURL):
                        headLen = len(checkURL)
                        self.__parseXMP(xmpBuffer[headLen:], length-headLen)
                    pass
                log("Leave", "[APP1]", "remove")

            elif marker == JPEG_APP2:
                log("Enter", "[APP2]", "add")
                self.__parseAPP2(length)
                log("Leave", "[APP2]", "remove")
                pass # TBD
            elif marker == JPEG_APP13:
                log("Enter", "[APP13]", "add")
                log("Leave", "[APP13]", "remove")
                pass # TBD
            seekTo(self._file, curPos+length-2)
Ejemplo n.º 2
0
    def parse(self, filePath):
        self._file = open(filePath)
        seekTo(self._file, 0)
        first = getCharToOrd(self._file)
        marker = getCharToOrd(self._file)
        if (first != 0xff or marker != JPEG_SOI):
            assert False, "Not in JPEG format !!"

        while (marker):
            first = getCharToOrd(self._file)
            if first != 0xff or first < 0:
                break
            marker = getCharToOrd(self._file)
            log("%s-%s" % (hex(first), hex(marker)))
            length = getBytes2(self._file)
            curPos = nowAt(self._file)
            log("length= %d, curPos=%d" % (length, curPos))

            if marker in [JPEG_EOI, JPEG_SOS]:
                log("EOI or SOS ... exit parsing")
                break
            elif marker == JPEG_APP0:
                log("Enter", "[APP0]", "add")
                log("Leave", "[APP0]", "remove")
                pass  # TBD
            elif marker == JPEG_APP1:
                log("Enter", "[APP1]", "add")
                header = getChar(self._file, 4)
                log("header = %s" % (header))
                if header.lower() == 'exif':
                    self.__parseAPP1(curPos + 6, curPos, curPos + length - 2)
                elif header.lower() == 'http':
                    seekTo(self._file, curPos)
                    xmpBuffer = getChar(self._file, length)
                    checkURL = "http://ns.adobe.com/xap/1.0/"
                    if xmpBuffer.startswith(checkURL):
                        headLen = len(checkURL)
                        self.__parseXMP(xmpBuffer[headLen:], length - headLen)
                    pass
                log("Leave", "[APP1]", "remove")

            elif marker == JPEG_APP2:
                log("Enter", "[APP2]", "add")
                self.__parseAPP2(length)
                log("Leave", "[APP2]", "remove")
                pass  # TBD
            elif marker == JPEG_APP13:
                log("Enter", "[APP13]", "add")
                log("Leave", "[APP13]", "remove")
                pass  # TBD
            seekTo(self._file, curPos + length - 2)
Ejemplo n.º 3
0
        def parseTagTable():
            log("Enter", "[ICCProfileTagTable]", "add")
            tagCount = getBytes4(self._fd)
            log("Tag count = %d"%(tagCount))
            for idx in xrange(tagCount):
                tagStartPos = nowAt(self._fd)
                sig = ''.join(getChar(self._fd) for _ in xrange(4))
                offset = getBytes4(self._fd)
                size = getBytes4(self._fd)
                seekTo(self._fd, basePos+offset)
                log("Tag sig(%s) / offset(%d) / size(%d) / basePos(%d) / tagSigPos(%d) / tagTypePos(%d) "%(sig, offset, size, basePos, tagStartPos, basePos+offset))
                typeDesc = ''.join(getChar(self._fd) for _ in xrange(4))
                log("Type Desc(%s)"%(typeDesc))
                sigDescObj = GetSigObject(sig, typeDesc, self._fd, size, basePos+offset)
                assert sig not in self.__dicSig2TagInfo, "Check this file, two same sig !"
                self.__dicSig2TagInfo[sig] = sigDescObj
                seekTo(self._fd, tagStartPos+12)

            log("Leave", "[ICCProfileTagTable]", "remove")
            pprint.pprint(self.__dicSig2TagInfo)
            pass
Ejemplo n.º 4
0
def GetMlucHelper(_fd, sig, tagStartPos):
    reserved = getBytes4(_fd)
    assert reserved == 0
    numOfRecords = getBytes4(_fd)
    recordSize = getBytes4(_fd)
    log(" numOfRecords = %d / recordSize = %s"%(numOfRecords, recordSize))

    sigDescObj = MultiLocalizedUnicode(sig)
    for _ in xrange(numOfRecords):
        langCode = ''.join(getChar(_fd) for i in xrange(2))
        langCountryCode = ''.join(getChar(_fd) for i in xrange(2))
        lenRecordString = getBytes4(_fd)
        offsetRecordString = getBytes4(_fd)

        here = nowAt(_fd)
        seekTo(_fd, tagStartPos + offsetRecordString)
        uniBytes = getChar(_fd, lenRecordString)
        # TODO : Think a better way to store these special unicode glyph
        uniChar = unicode(uniBytes, errors='replace')
        log(" uniChar = %s"%(uniChar))
        sigDescObj.add(langCode, langCountryCode, uniChar)
        seekTo(_fd, here)
    return sigDescObj
Ejemplo n.º 5
0
 def __parseAPP2(self, length):
     curPos = nowAt(self._file)
     iptcData = getChar(self._file, length)
     iccIdentifier = "ICC_PROFILE"
     if (iptcData.startswith(iccIdentifier)):
         iccData = iptcData[len(iccIdentifier) + 1:]
         iccLen = 0
         if ord(iccData[0]) == 0x01 and ord(iccData[1]) == 0x01:
             iccLen = length - 14
         elif ord(iccData[0]) == 0x01:  # multi-page, support header only
             iccLen = 128
         else:
             log("Wrong ICC Profile format !")
             return
         seekTo(self._file, curPos + 14)
         from ICCProfileParser import ICCProfileParser
         iccParser = ICCProfileParser(self._file)
         iccParser.parse()
     else:
         log("Wrong ICC Profile format !")
         assert False
 def __parseAPP2(self, length):
     curPos = nowAt(self._file)
     iptcData = getChar(self._file, length)
     iccIdentifier = "ICC_PROFILE"
     if (iptcData.startswith(iccIdentifier)):
         iccData = iptcData[len(iccIdentifier)+1:]
         iccLen = 0
         if ord(iccData[0]) == 0x01 and ord(iccData[1]) == 0x01:
             iccLen = length -14
         elif ord(iccData[0]) == 0x01: # multi-page, support header only
             iccLen = 128
         else:
             log("Wrong ICC Profile format !")
             return
         seekTo(self._file, curPos+14)
         from ICCProfileParser import ICCProfileParser
         iccParser = ICCProfileParser(self._file)
         iccParser.parse()
     else:
         log("Wrong ICC Profile format !")
         assert False
Ejemplo n.º 7
0
    def __getDataFromFormat(self, tag, format, size):
        from array import array
        bytesPerComp = EXIF_TIFF_DATAFORMAT_LIST[format]
        entry = IFDEntry(tag, bytesPerComp)
        #print 'format(%d)/Size(%d)'%(format, size)
        lstValue = []
        if format in [1, 6, 7]:
            # unsigned byte / # signed byte / # undefined
            data = array('b', getChar(self._file, size))
            pass
        elif format == 2:
            # ascii string
            data = array('c', getChar(self._file, size))
            pass
        elif format in [3, 8]:
            # unsigned short / # signed short
            while size > 0:
                v = getBytes2(self._file, self._orderAPP1)
                lstValue.append(v)
                size -= 2
            encode = 'H' if format == 3 else 'h'
            data = array('H', lstValue)
            pass
        elif format in [4, 9]:
            # unsigned long / # signed long
            while size > 0:
                v = getBytes4(self._file, self._orderAPP1)
                lstValue.append(v)
                size -= 4
            encode = 'L' if format == 4 else 'l'
            data = array('L', lstValue)
            pass
        elif format in [5, 10]:
            # unsigned rational / # signed rational
            while size > 0:
                numerator = getBytes4(self._file, self._orderAPP1)
                denominator = getBytes4(self._file, self._orderAPP1)
                size -= 8
                lstValue.append(float(numerator) / float(denominator))
            data = array('d', lstValue)
            pass
        elif format == 11:
            # signed float
            while size > 0:
                v = getBytes4(self._file, self._orderAPP1)
                lstValue.append(v)
                size -= 4
            data = array('f', lstValue)
            pass
        elif format == 12:
            # double float
            while size > 0:
                numerator = getBytes4(self._file, self._orderAPP1)
                denominator = getBytes4(self._file, self._orderAPP1)
                size -= 8
                lstValue.append(float(numerator) / float(denominator))
            data = array('d', lstValue)
            pass
        entry.setData(data)

        log(" --- tag(%s), %s" % (getTagStringByValue(tag), str(data)))
        return entry
    def __getDataFromFormat(self, tag, format, size):
        from array import array
        bytesPerComp = EXIF_TIFF_DATAFORMAT_LIST[format]
        entry = IFDEntry(tag, bytesPerComp)
        #print 'format(%d)/Size(%d)'%(format, size)
        lstValue = []
        if format in [1, 6, 7]:
            # unsigned byte / # signed byte / # undefined
            data = array('b', getChar(self._file, size))
            pass
        elif format == 2:
            # ascii string
            data = array('c', getChar(self._file, size))
            pass
        elif format in [3, 8]:
            # unsigned short / # signed short
            while size > 0:
                v = getBytes2(self._file, self._orderAPP1)
                lstValue.append(v)
                size -= 2
            encode = 'H' if format == 3 else 'h'
            data = array('H', lstValue)
            pass
        elif format in [4, 9]:
            # unsigned long / # signed long
            while size > 0:
                v = getBytes4(self._file, self._orderAPP1)
                lstValue.append(v)
                size -= 4
            encode = 'L' if format == 4 else 'l'
            data = array('L', lstValue)
            pass
        elif format in [5, 10]:
            # unsigned rational / # signed rational
            while size > 0:
                numerator = getBytes4(self._file, self._orderAPP1)
                denominator = getBytes4(self._file, self._orderAPP1)
                size -= 8
                lstValue.append(float(numerator) / float(denominator))
            data = array('d', lstValue)
            pass
        elif format == 11:
            # signed float
            while size > 0:
                v = getBytes4(self._file, self._orderAPP1)
                lstValue.append(v)
                size -= 4
            data = array('f', lstValue)
            pass
        elif format == 12:
            # double float
            while size > 0:
                numerator = getBytes4(self._file, self._orderAPP1)
                denominator = getBytes4(self._file, self._orderAPP1)
                size -= 8
                lstValue.append(float(numerator) / float(denominator))
            data = array('d', lstValue)
            pass
        entry.setData(data)

        log(" --- tag(%s), %s"%(getTagStringByValue(tag), str(data)))
        return entry
Ejemplo n.º 9
0
        def parseHeader():
            log("Enter", "[ICCProfileHeader]", "add")
            profileSize = getBytes4(self._fd)

            cmmType = ''.join(getChar(self._fd) for _ in xrange(4))
            lstVer = [str(getCharToOrd(self._fd)) for _ in xrange(4)]
            self.__dicHeaderInfo[H_CMM_TYPE] = cmmType
            self.__dicHeaderInfo[H_VERSION] = lstVer[0] + "." + lstVer[1]

            deviceClass = ''.join(getChar(self._fd) for _ in xrange(4))
            colorSpaceOfData = ''.join(getChar(self._fd) for _ in xrange(4))
            pcs = ''.join(getChar(self._fd) for _ in xrange(4))
            self.__dicHeaderInfo[H_DEVICE_CLASS] = dicDevCls2Name.get(deviceClass, "Not found")
            self.__dicHeaderInfo[H_COLOR_SPACE] = colorSpaceOfData.strip()
            self.__dicHeaderInfo[H_PROFILE_CONNECTION_SPACE] = pcs.strip()

            lstDatetime = [getBytes2(self._fd) for _ in xrange(6)]
            signature = ''.join(getChar(self._fd) for _ in xrange(4))
            assert signature == "acsp", "Not a standard ICC Profile !!"
            primaryPlatform = ''.join(getChar(self._fd) for _ in xrange(4))

            def getBitsList(numBytes):
                lstBits = []
                for _ in xrange(numBytes):
                    bits_short = bin(getCharToOrd(self._fd))[2:]
                    bits_full = '00000000'[len(bits_short):] + bits_short
                    lstBits.extend([int(b) for b in bits_full])
                return lstBits

            lstProfileFlags = getBitsList(4)
            self.__dicHeaderInfo[H_CREATE_DATETIME] = "Datatime = %d/%d/%d-%d:%d:%d"%tuple(lstDatetime)
            self.__dicHeaderInfo[H_SIGNATURE] = signature
            self.__dicHeaderInfo[H_PLATFORM] = dicPlatformSig2Desc.get(primaryPlatform, "Not found")
            self.__dicHeaderInfo[H_IS_EMBEDED] = True if lstProfileFlags[0] == 1 else False
            self.__dicHeaderInfo[H_USED_INDENDENTLY] = False if lstProfileFlags[1] == 1 else True

            deviceManufacturer = ''.join(getChar(self._fd) for _ in xrange(4))
            deviceModel = ''.join(getChar(self._fd) for _ in xrange(4))
            lstDeviceAttributes = getBitsList(8)
            renderingIntent, zeroPadding = getBytes2(self._fd), getBytes2(self._fd)

            self.__dicHeaderInfo[H_DEVICE_MANUFACTURER] = deviceManufacturer
            self.__dicHeaderInfo[H_DEVICE_MODEL] = deviceModel
            self.__dicHeaderInfo[H_ATTR_T_R] = "Transparency" if lstDeviceAttributes[0] == 1 else "Reflective"
            self.__dicHeaderInfo[H_ATTR_M_G] = "Matte" if lstDeviceAttributes[1] == 1 else "Glossy"
            self.__dicHeaderInfo[H_RENDERING_INTENT] = dicRenderingIntent2Desc.get(renderingIntent, "Not found")

            intX, intY, intZ = getBytes4(self._fd), getBytes4(self._fd), getBytes4(self._fd)
            X = struct.unpack('f', struct.pack('i', intX))
            Y = struct.unpack('f', struct.pack('i', intY))
            Z = struct.unpack('f', struct.pack('i', intZ))
            CIEXYZ_X = X[0] / Y[0]
            CIEXYZ_Y = Y[0] / Y[0]
            CIEXYZ_Z = Z[0] / Y[0]

            profileCreator = ''.join(getChar(self._fd) for _ in xrange(4))
            profileID = [hex(getCharToOrd(self._fd)) for _ in xrange(16)]
            reserved = [hex(getCharToOrd(self._fd)) for _ in xrange(28)]

            self.__dicHeaderInfo[H_PROFILE_CREATOR] = profileCreator
            self.__dicHeaderInfo[H_PROFILE_D50_XYZ] = "(%f, %f, %f)"%(CIEXYZ_X, CIEXYZ_Y, CIEXYZ_Z)
            log("Header Information : \n%s "%(pprint.pformat(self.__dicHeaderInfo, indent=2)))
            log("Leave", "[ICCProfileHeader]", "remove")
Ejemplo n.º 10
0
def GetSigObject(sig, type, _fd, size, tagStartPos=None):
    # _fd is already seeked to starting point of data
    # 4bytes type(description) is included in size
    sigDescObj = None
    if sig == "A2B0":
        if type == "mAB ":
            sigDescObj = GetAToBHelper(_fd, sig, tagStartPos)
        elif type == "mft2":
            sigDescObj = GetMultiFunctionTableHelper(_fd, sig, tagStartPos)
        pass
    elif sig == "A2B1":
        if type == "mAB ":
            sigDescObj = GetAToBHelper(_fd, sig, tagStartPos)
        elif type == "mft2":
            sigDescObj = GetMultiFunctionTableHelper(_fd, sig, tagStartPos)
        pass
    elif sig == "A2B2":
        if type == "mAB ":
            sigDescObj = GetAToBHelper(_fd, sig, tagStartPos)
        elif type == "mft2":
            sigDescObj = GetMultiFunctionTableHelper(_fd, sig, tagStartPos)
        pass
    elif sig in ["bXYZ", "gXYZ", "rXYZ", "bkpt", "wtpt", "lumi"]:
        reserved = getBytes4(_fd)
        assert reserved == 0
        assert size == 20
        X, Y, Z = GetXYZHelper(_fd)
        log(" XYZ = (%f, %f, %f)"%(X, Y, Z))
        sigDescObj = XYZ(sig, X, Y, Z)
    elif sig == "B2A0":
        if type == "mBA ":
            sigDescObj = GetBToAHelper(_fd, sig, tagStartPos)
        elif type == "mft2":
            sigDescObj = GetMultiFunctionTableHelper(_fd, sig, tagStartPos)
    elif sig == "B2A1":
        if type == "mBA ":
            sigDescObj = GetBToAHelper(_fd, sig, tagStartPos)
        elif type == "mft2":
            sigDescObj = GetMultiFunctionTableHelper(_fd, sig, tagStartPos)
    elif sig == "B2A2":
        if type == "mBA ":
            sigDescObj = GetBToAHelper(_fd, sig, tagStartPos)
        elif type == "mft2":
            sigDescObj = GetMultiFunctionTableHelper(_fd, sig, tagStartPos)
    elif sig == "calt":
        pass
    elif sig == "ciis":
        content = ''.join(getChar(_fd) for _ in xrange(size-4)).strip('\0x00')
        log(" ciis content = %s "%(dicColorimetricIntentImageState2Desc.get(content, "Unknown")))
        sigDescObj = Signature(sig, content)
    elif sig == "targ":
        pass
    elif sig == "cprt":
        if type == "mluc":
            sigDescObj = GetMlucHelper(_fd, sig, tagStartPos)
        else:
            content = ''.join(getChar(_fd) for _ in xrange(size-4))
            log(" cpry content = %s"%(content))
            sigDescObj = Text(sig, content)
        pass
    elif sig == "chad":
        reserved = getBytes4(_fd)
        assert reserved == 0
        assert size == 44
        mat = []
        for _ in xrange(9):
            intUnsigned = getBytes2(_fd)
            intSigned = intUnsigned - 65536 if intUnsigned >= 32768 else intUnsigned
            fracPart = getBytes2(_fd)
            v = intSigned + float(fracPart) / 65536
            mat.append(v)
        log(" chad = %s"%(str(mat)))
        sigDescObj = S15Fixed16Array(sig, mat)
        pass
    elif sig == "gamt":
        pass
    elif sig == "kTRC":
        pass
    elif sig == "meas":
        reserved = getBytes4(_fd)
        assert reserved == 0
        assert size == 36
        obs = dicStdObserver2Desc.get(hex(getBytes4(_fd)), dicStdObserver2Desc[hex(0)])
        tristimulusXYZ = GetXYZHelper(_fd)
        geo = dicGeometry2Desc.get(hex(getBytes4(_fd)), dicGeometry2Desc[hex(0)])
        flareInt, flareFractional = getBytes2(_fd), getBytes2(_fd)
        flare = flareInt + float(flareFractional) / 65536
        illuminantType = dicIlluminantType2Desc.get(hex(getBytes4(_fd)), dicIlluminantType2Desc[hex(0)])
        log(" obs(%s) / triXYZ(%s) / geo(%s) / flare(%f) / illu(%s)"%(obs, str(tristimulusXYZ),\
        geo, flare, illuminantType))
        sigDescObj = Measurement(sig, obs, tristimulusXYZ, geo, flare, illuminantType)
    elif sig == "ncol":
        pass
    elif sig == "ncl2":
        pass
    elif sig == "pre0":
        pass
    elif sig == "pre1":
        pass
    elif sig == "pre2":
        pass
    elif sig in ["dscm"]:
        if type == "mluc":
            sigDescObj = GetMlucHelper(_fd, sig, tagStartPos)

    elif sig in ["desc", "dmdd", "dmnd", "scrd", "vued"]:
        if type == "mluc":
            sigDescObj = GetMlucHelper(_fd, sig, tagStartPos)
        else:
            reserved = getBytes4(_fd)
            assert reserved == 0
            asciiCount = getBytes4(_fd)
            log(" asciiCount = %d"%(asciiCount))
            asciiInvariantDesc = getChar(_fd, asciiCount)
            log(" asciiInvariantDesc = %s"%(asciiInvariantDesc))
            uniLangCode = getBytes4(_fd)
            uniCount = getBytes4(_fd)
            log(" uniLangCode, uniCount = %d, %d"%(uniLangCode, uniCount))
            uniLocalizableDesc = None
            if uniCount != 0:
                uniLocalizableDesc = u""
                for _ in xrange(uniCount):
                    uniLocalizableDesc.join(getBytes2(_fd).decode("utf-8", "ignore"))
                log(" uniLocalizableDesc = %s"%(uniLocalizableDesc))
            scriptCode = getBytes2(_fd)
            scriptCount = getCharToOrd(_fd)
            log(" scriptCode, scriptCount = %d, %d"%(scriptCode, scriptCount))
            localMacintoshDesc = None
            if scriptCount != 0:
                localMacintoshDesc = getChar(_fd, min(67,scriptCount))
                log(" localMacintoshDesc = %s"%(localMacintoshDesc))
            sigDescObj = TextDescription(sig, asciiInvariantDesc,\
                                         uniLocalizableDesc, localMacintoshDesc)
        pass
    elif sig == "pseq":
        pass
    elif sig == "psd0":
        pass
    elif sig == "psd1":
        pass
    elif sig == "psd2":
        pass
    elif sig == "psd3":
        pass
    elif sig == "ps2s":
        pass
    elif sig == "ps2i":
        pass
    elif sig == "rig0":
        content = ''.join(getChar(_fd) for _ in xrange(size-4)).strip('\0x00')
        log(" rig0 content = %s "%(content))
        sigDescObj = Signature(sig, content)
    elif sig in ["rTRC", "gTRC", "bTRC"]:
        sigDescObj = GetCurveHelper(_fd, sig)
    elif sig == "scrn":
        pass
    elif sig == "tech":
        content = ''.join(getChar(_fd) for _ in xrange(size-4)).strip('\0x00')
        log(" tech content = %s "%(dicTechType2Desc.get(content, 'None')))
        sigDescObj = Signature(sig, content)
        pass
    elif sig == "bfd ":
        pass
    elif sig == "vued":
        pass
    elif sig == "view":
        reserved = getBytes4(_fd)
        assert reserved == 0
        illuminantXYZ = GetXYZHelper(_fd)
        surroundXYZ = GetXYZHelper(_fd)
        log(" illXYZ = (%f, %f, %f)"%(illuminantXYZ))
        log(" surXYZ = (%f, %f, %f)"%(surroundXYZ))
        illuminantType = dicIlluminantType2Desc.get(hex(getBytes4(_fd)), dicIlluminantType2Desc[hex(0)])
        sigDescObj = ViewingConditions(sig, illuminantXYZ, surroundXYZ, illuminantType)
        log(" illuminantType = %s"%illuminantType)

    return sigDescObj
Ejemplo n.º 11
0
def GetAToBHelper(_fd, sig, tagStartPos, reverse=False):
    reserved = getBytes4(_fd)
    assert reserved == 0
    numOfInputChannel = getCharToOrd(_fd)
    numOfOutputChannel = getCharToOrd(_fd)
    padding = getBytes2(_fd)
    log(" Input(%d) , Output(%d), padding(%d)"%(numOfInputChannel, numOfOutputChannel, padding))
    assert padding == 0

    sigDescObj = None
    lstBCurve = []
    mMat = None
    lstMCurve = []
    clut = []
    lstACurve = []

    offset2BCurve = getBytes4(_fd)
    if offset2BCurve != 0:
        here = nowAt(_fd)
        seekTo(_fd, tagStartPos + offset2BCurve)
        for _ in xrange(numOfOutputChannel):
            subType = getChar(_fd, 4)
            log(" B Curve subtype = %s"%(subType))
            if subType == "para":
                sigSubDescObj = GetParaCurveHelper(_fd, sig)
                lstBCurve.append(sigSubDescObj)
            elif subType == "curv":
                sigSubDescObj = GetCurveHelper(_fd, sig)
                lstBCurve.append(sigSubDescObj)
        seekTo(_fd, here)
        assert len(lstBCurve) == numOfOutputChannel

    offset2Matrix = getBytes4(_fd)
    if offset2Matrix != 0:
        here = nowAt(_fd)
        seekTo(_fd, tagStartPos + offset2Matrix)
        mat = []
        for _ in xrange(12):
            intUnsigned = getBytes2(_fd)
            intSigned = intUnsigned - 65536 if intUnsigned >= 32768 else intUnsigned
            fracPart = getBytes2(_fd)
            v = intSigned + float(fracPart) / 65536
            mat.append(v)
        log(" Matrix = %s"%(str(mat)))
        mMat = S15Fixed16Array(sig, mat)
        seekTo(_fd, here)

    offset2MCurve = getBytes4(_fd)
    if offset2MCurve != 0:
        here = nowAt(_fd)
        seekTo(_fd, tagStartPos + offset2MCurve)
        for _ in xrange(numOfOutputChannel):
            subType = getChar(_fd, 4)
            log(" M Curve subtype = %s"%(subType))
            if subType == "para":
                sigSubDescObj = GetParaCurveHelper(_fd, sig)
                lstMCurve.append(sigSubDescObj)
            elif subType == "curv":
                sigSubDescObj = GetCurveHelper(_fd, sig)
                lstMCurve.append(sigSubDescObj)
        seekTo(_fd, here)
        assert len(lstMCurve) == numOfOutputChannel

    offset2CLUT = getBytes4(_fd)
    if offset2CLUT != 0:
        # TODO : Check the implementation correctness
        here = nowAt(_fd)
        seekTo(_fd, tagStartPos + offset2CLUT)

        lstGridPoints = []
        for _ in xrange(16):
            gridPts = getCharToOrd(_fd)
            if _ >= numOfInputChannel:
                assert gridPts == 0
            lstGridPoints.append(gridPts)
        precision = getCharToOrd(_fd)
        padding = getBytes3(_fd)
        log(" >>> lstGridPoints : %s"%(str(lstGridPoints)))
        log(" >>> precision : %s / padding %s "%(str(precision), str(padding)))
        assert padding == 0
        getDataPoint = getBytes2 if precision == 2 else getCharToOrd

        def fn(x, y):
            return x * y if y != 0 else x
        totalCLUTPts = reduce(fn, lstGridPoints)
        for _ in xrange(totalCLUTPts):
            tmp = []
            for __ in xrange(numOfOutputChannel):
                tmp.append(getDataPoint(_fd))
            clut.append(tmp)
        seekTo(_fd, here)

    offset2ACurve = getBytes4(_fd)
    if offset2ACurve != 0:
        here = nowAt(_fd)
        seekTo(_fd, tagStartPos + offset2ACurve)
        for _ in xrange(numOfOutputChannel):
            subType = getChar(_fd, 4)
            log(" A Curve subtype = %s"%(subType))
            if subType == "para":
                sigSubDescObj = GetParaCurveHelper(_fd, sig)
                lstACurve.append(sigSubDescObj)
            elif subType == "curv":
                sigSubDescObj = GetCurveHelper(_fd, sig)
                lstACurve.append(sigSubDescObj)
        seekTo(_fd, here)
        assert len(lstACurve) == numOfOutputChannel

    log(" O2B(%d) / O2mat(%d) / O2M(%d) / O2CLUT(%d) / O2A(%d)"%(offset2BCurve,\
        offset2Matrix, offset2MCurve, offset2CLUT, offset2ACurve))

    if reverse:
        sigDescObj = LutBToA(sig, lstBCurve, mMat, lstMCurve, clut, lstACurve)
    else:
        sigDescObj = LutAToB(sig, lstBCurve, mMat, lstMCurve, clut, lstACurve)
    return sigDescObj