/*
 * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include "sun_java2d_cmm_lcms_LCMS.h"
#include "sun_java2d_cmm_lcms_LCMSImageLayout.h"
#include "jni_util.h"
#include "Trace.h"
#include "Disposer.h"
#include <lcms2.h>
#include <lcms2_plugin.h>
#include "jlong.h"

#define SigMake(a,b,c,d) \
                    ( ( ((int) ((unsigned char) (a))) << 24) | \
                      ( ((int) ((unsigned char) (b))) << 16) | \
                      ( ((int) ((unsigned char) (c))) <<  8) | \
                          (int) ((unsigned char) (d)))

#define TagIdConst(a, b, c, d) \
                ((int) SigMake ((a), (b), (c), (d)))

#define SigHead TagIdConst('h','e','a','d')

#define DT_BYTE     sun_java2d_cmm_lcms_LCMSImageLayout_DT_BYTE
#define DT_SHORT    sun_java2d_cmm_lcms_LCMSImageLayout_DT_SHORT
#define DT_INT      sun_java2d_cmm_lcms_LCMSImageLayout_DT_INT

/* Default temp profile list size */
#define DF_ICC_BUF_SIZE 32

#define ERR_MSG_SIZE 256

#ifdef _MSC_VER
# ifndef snprintf
#       define snprintf  _snprintf
# endif
#endif

typedef struct lcmsProfile_s {
    cmsHPROFILE pf;
} lcmsProfile_t, *lcmsProfile_p;

typedef union {
    cmsTagSignature cms;
    jint j;
} TagSignature_t, *TagSignature_p;

JavaVM *javaVM;

void errorHandler(cmsContext ContextID, cmsUInt32Number errorCode,
                  const char *errorText) {
    JNIEnv *env;
    char errMsg[ERR_MSG_SIZE];

    int count = snprintf(errMsg, ERR_MSG_SIZE,
                          "LCMS error %d: %s", errorCode, errorText);
    if (count < 0 || count >= ERR_MSG_SIZE) {
        count = ERR_MSG_SIZE - 1;
    }
    errMsg[count] = 0;

    (*javaVM)->AttachCurrentThread(javaVM, (void**)&env, NULL);
    if (!(*env)->ExceptionCheck(env)) { // errorHandler may throw it before
        JNU_ThrowByName(env, "java/awt/color/CMMException", errMsg);
    }
}

JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *jvm, void *reserved) {
    javaVM = jvm;

    cmsSetLogErrorHandler(errorHandler);
    return JNI_VERSION_1_6;
}

void LCMS_freeProfile(JNIEnv *env, jlong ptr) {
    lcmsProfile_p p = (lcmsProfile_p)jlong_to_ptr(ptr);

    if (p != NULL) {
        if (p->pf != NULL) {
            cmsCloseProfile(p->pf);
        }
        free(p);
    }
}

void LCMS_freeTransform(JNIEnv *env, jlong ID)
{
    cmsHTRANSFORM sTrans = jlong_to_ptr(ID);
    /* Passed ID is always valid native ref so there is no check for zero */
    cmsDeleteTransform(sTrans);
}

/*
 * Throw an IllegalArgumentException and init the cause.
 */
static void ThrowIllegalArgumentException(JNIEnv *env, const char *msg) {
    jthrowable cause = (*env)->ExceptionOccurred(env);
    if (cause != NULL) {
        (*env)->ExceptionClear(env);
    }
    jstring str = JNU_NewStringPlatform(env, msg);
    if (str != NULL) {
        jobject iae = JNU_NewObjectByName(env,
                                "java/lang/IllegalArgumentException",
                                "(Ljava/lang/String;Ljava/lang/Throwable;)V",
                                str, cause);
        if (iae != NULL) {
            (*env)->Throw(env, iae);
        }
    }
}

/*
 * Class:     sun_java2d_cmm_lcms_LCMS
 * Method:    createNativeTransform
 * Signature: ([JIIZIZLjava/lang/Object;)J
 */
JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform
  (JNIEnv *env, jclass cls, jlongArray profileIDs, jint renderingIntent,
   jint inFormatter, jint outFormatter, jobject disposerRef)
{
    cmsHPROFILE _iccArray[DF_ICC_BUF_SIZE];
    cmsHPROFILE *iccArray = &_iccArray[0];
    cmsHTRANSFORM sTrans = NULL;
    int i, j, size;
    jlong* ids;

    size = (*env)->GetArrayLength (env, profileIDs);
    ids = (*env)->GetLongArrayElements(env, profileIDs, 0);
    if (ids == NULL) {
        // An exception should have already been thrown.
        return 0L;
    }

    if (DF_ICC_BUF_SIZE < size*2) {
        iccArray = (cmsHPROFILE*) malloc(
            size*2*sizeof(cmsHPROFILE));
        if (iccArray == NULL) {
            (*env)->ReleaseLongArrayElements(env, profileIDs, ids, 0);

            J2dRlsTraceLn(J2D_TRACE_ERROR, "getXForm: iccArray == NULL");
            return 0L;
        }
    }

    j = 0;
    for (i = 0; i < size; i++) {
        cmsColorSpaceSignature cs;
        lcmsProfile_p profilePtr = (lcmsProfile_p)jlong_to_ptr(ids[i]);
        cmsHPROFILE icc = profilePtr->pf;

        iccArray[j++] = icc;

        /* Middle non-abstract profiles should be doubled before passing to
         * the cmsCreateMultiprofileTransform function
         */

        cs = cmsGetColorSpace(icc);
        if (size > 2 && i != 0 && i != size - 1 &&
            cs != cmsSigXYZData && cs != cmsSigLabData)
        {
            iccArray[j++] = icc;
        }
    }

    cmsUInt32Number dwFlags = 0;
    if (T_EXTRA(inFormatter) > 0 && T_EXTRA(outFormatter) > 0) {
        dwFlags |= cmsFLAGS_COPY_ALPHA;
    }

    sTrans = cmsCreateMultiprofileTransform(iccArray, j,
        inFormatter, outFormatter, renderingIntent, dwFlags);

    (*env)->ReleaseLongArrayElements(env, profileIDs, ids, 0);

    if (sTrans == NULL) {
        J2dRlsTraceLn(J2D_TRACE_ERROR, "LCMS_createNativeTransform: "
                                       "sTrans == NULL");
        if (!(*env)->ExceptionCheck(env)) { // errorHandler may throw it
            JNU_ThrowByName(env, "java/awt/color/CMMException",
                            "Cannot get color transform");
        }
    } else {
        Disposer_AddRecord(env, disposerRef, LCMS_freeTransform, ptr_to_jlong(sTrans));
    }

    if (iccArray != &_iccArray[0]) {
        free(iccArray);
    }
    return ptr_to_jlong(sTrans);
}


/*
 * Class:     sun_java2d_cmm_lcms_LCMS
 * Method:    loadProfileNative
 * Signature: ([BLjava/lang/Object;)J
 */
JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative
  (JNIEnv *env, jclass cls, jbyteArray data, jobject disposerRef)
{
    jbyte* dataArray;
    jint dataSize;
    lcmsProfile_p sProf = NULL;
    cmsHPROFILE pf;

    if (JNU_IsNull(env, data)) {
        ThrowIllegalArgumentException(env, "Invalid profile data");
        return 0L;
    }

    dataArray = (*env)->GetByteArrayElements (env, data, 0);
    if (dataArray == NULL) {
        // An exception should have already been thrown.
        return 0L;
    }

    dataSize = (*env)->GetArrayLength (env, data);

    pf = cmsOpenProfileFromMem((const void *)dataArray,
                                     (cmsUInt32Number) dataSize);

    (*env)->ReleaseByteArrayElements (env, data, dataArray, 0);

    if (pf == NULL) {
        ThrowIllegalArgumentException(env, "Invalid profile data");
    } else {
        /* Sanity check: try to save the profile in order
         * to force basic validation.
         */
        cmsUInt32Number pfSize = 0;
        if (!cmsSaveProfileToMem(pf, NULL, &pfSize) ||
            pfSize < sizeof(cmsICCHeader))
        {
            ThrowIllegalArgumentException(env, "Invalid profile data");
            cmsCloseProfile(pf);
            pf = NULL;
        }
    }

    if (pf != NULL) {
        // create profile holder
        sProf = (lcmsProfile_p)malloc(sizeof(lcmsProfile_t));
        if (sProf != NULL) {
            // register the disposer record
            sProf->pf = pf;
            Disposer_AddRecord(env, disposerRef, LCMS_freeProfile, ptr_to_jlong(sProf));
        } else {
            cmsCloseProfile(pf);
        }
    }

    return ptr_to_jlong(sProf);
}

/*
 * Class:     sun_java2d_cmm_lcms_LCMS
 * Method:    getProfileDataNative
 * Signature: (J)[B
 */
JNIEXPORT jbyteArray JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileDataNative
  (JNIEnv *env, jclass cls, jlong id)
{
    lcmsProfile_p sProf = (lcmsProfile_p)jlong_to_ptr(id);
    cmsUInt32Number pfSize = 0;

    // determine actual profile size
    if (!cmsSaveProfileToMem(sProf->pf, NULL, &pfSize)) {
        if (!(*env)->ExceptionCheck(env)) { // errorHandler may throw it
            JNU_ThrowByName(env, "java/awt/color/CMMException",
                            "Can not access specified profile.");
        }
        return NULL;
    }

    jbyteArray data = (*env)->NewByteArray(env, pfSize);
    if (data == NULL) {
        // An exception should have already been thrown.
        return NULL;
    }

    jbyte* dataArray = (*env)->GetByteArrayElements(env, data, 0);
    if (dataArray == NULL) {
        // An exception should have already been thrown.
        return NULL;
    }

    cmsBool status = cmsSaveProfileToMem(sProf->pf, dataArray, &pfSize);

    (*env)->ReleaseByteArrayElements(env, data, dataArray, 0);

    if (!status) {
        if (!(*env)->ExceptionCheck(env)) { // errorHandler may throw it
            JNU_ThrowByName(env, "java/awt/color/CMMException",
                            "Can not access specified profile.");
        }
        return NULL;
    }
    return data;
}

/* Get profile header info */
static cmsBool _getHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize);
static cmsBool _setHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize);
static cmsHPROFILE _writeCookedTag(cmsHPROFILE pfTarget, cmsTagSignature sig, jbyte *pData, jint size);


/*
 * Class:     sun_java2d_cmm_lcms_LCMS
 * Method:    getTagNative
 * Signature: (JI)[B
 */
JNIEXPORT jbyteArray JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagNative
  (JNIEnv *env, jclass cls, jlong id, jint tagSig)
{
    lcmsProfile_p sProf = (lcmsProfile_p)jlong_to_ptr(id);
    TagSignature_t sig;
    cmsUInt32Number tagSize;

    jbyte* dataArray = NULL;
    jbyteArray data = NULL;

    cmsUInt32Number bufSize;

    sig.j = tagSig;

    if (tagSig == SigHead) {
        cmsBool status;

        // allocate java array
        bufSize = sizeof(cmsICCHeader);
        data = (*env)->NewByteArray(env, bufSize);

        if (data == NULL) {
            // An exception should have already been thrown.
            return NULL;
        }

        dataArray = (*env)->GetByteArrayElements (env, data, 0);

        if (dataArray == NULL) {
            // An exception should have already been thrown.
            return NULL;
        }

        status = _getHeaderInfo(sProf->pf, dataArray, bufSize);

        (*env)->ReleaseByteArrayElements (env, data, dataArray, 0);

        if (!status) {
            if (!(*env)->ExceptionCheck(env)) { // errorHandler may throw it
                JNU_ThrowByName(env, "java/awt/color/CMMException",
                                "ICC Profile header not found");
            }
            return NULL;
        }

        return data;
    }

    if (cmsIsTag(sProf->pf, sig.cms)) {
        tagSize = cmsReadRawTag(sProf->pf, sig.cms, NULL, 0);
    } else {
        if (!(*env)->ExceptionCheck(env)) { // errorHandler may throw it
            JNU_ThrowByName(env, "java/awt/color/CMMException",
                            "ICC profile tag not found");
        }
        return NULL;
    }

    // allocate java array
    data = (*env)->NewByteArray(env, tagSize);
    if (data == NULL) {
        // An exception should have already been thrown.
        return NULL;
    }

    dataArray = (*env)->GetByteArrayElements (env, data, 0);

    if (dataArray == NULL) {
        // An exception should have already been thrown.
        return NULL;
    }

    bufSize = cmsReadRawTag(sProf->pf, sig.cms, dataArray, tagSize);

    (*env)->ReleaseByteArrayElements (env, data, dataArray, 0);

    if (bufSize != tagSize) {
        if (!(*env)->ExceptionCheck(env)) { // errorHandler may throw it
            JNU_ThrowByName(env, "java/awt/color/CMMException",
                            "Can not get tag data.");
        }
        return NULL;
    }
    return data;
}

/*
 * Class:     sun_java2d_cmm_lcms_LCMS
 * Method:    setTagDataNative
 * Signature: (JI[B)V
 */
JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative
  (JNIEnv *env, jclass cls, jlong id, jint tagSig, jbyteArray data)
{
    lcmsProfile_p sProf = (lcmsProfile_p)jlong_to_ptr(id);
    cmsHPROFILE pfReplace = NULL;

    TagSignature_t sig;
    cmsBool status = FALSE;
    jbyte* dataArray;
    int tagSize;

    sig.j = tagSig;

    if (JNU_IsNull(env, data)) {
        ThrowIllegalArgumentException(env, "Can not write tag data.");
        return;
    }

    tagSize =(*env)->GetArrayLength(env, data);

    dataArray = (*env)->GetByteArrayElements(env, data, 0);

    if (dataArray == NULL) {
        // An exception should have already been thrown.
        return;
    }

    if (tagSig == SigHead) {
        status  = _setHeaderInfo(sProf->pf, dataArray, tagSize);
    } else {
        /*
        * New strategy for generic tags: create a place holder,
        * dump all existing tags there, dump externally supplied
        * tag, and return the new profile to the java.
        */
        pfReplace = _writeCookedTag(sProf->pf, sig.cms, dataArray, tagSize);
        status = (pfReplace != NULL);
    }

    (*env)->ReleaseByteArrayElements(env, data, dataArray, 0);

    if (!status) {
        ThrowIllegalArgumentException(env, "Can not write tag data.");
    } else if (pfReplace != NULL) {
        cmsCloseProfile(sProf->pf);
        sProf->pf = pfReplace;
    }
}

static void *getILData(JNIEnv *env, jobject data, jint type) {
    switch (type) {
        case DT_BYTE:
            return (*env)->GetByteArrayElements(env, data, 0);
        case DT_SHORT:
            return (*env)->GetShortArrayElements(env, data, 0);
        case DT_INT:
            return (*env)->GetIntArrayElements(env, data, 0);
        default:
            return NULL;
    }
}

static void releaseILData(JNIEnv *env, void *pData, jint type, jobject data,
                          jint mode) {
    switch (type) {
        case DT_BYTE:
            (*env)->ReleaseByteArrayElements(env, data, (jbyte *) pData, mode);
            break;
        case DT_SHORT:
            (*env)->ReleaseShortArrayElements(env, data, (jshort *) pData, mode);
            break;
        case DT_INT:
            (*env)->ReleaseIntArrayElements(env, data, (jint *) pData, mode);
            break;
    }
}

/*
 * Class:     sun_java2d_cmm_lcms_LCMS
 * Method:    colorConvert
 * Signature: (JIIIIIIZZLjava/lang/Object;Ljava/lang/Object;)V
 */
JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_colorConvert
  (JNIEnv *env, jclass cls, jlong ID, jint width, jint height, jint srcOffset,
   jint srcNextRowOffset, jint dstOffset, jint dstNextRowOffset,
   jobject srcData, jobject dstData, jint srcDType, jint dstDType)
{
    cmsHTRANSFORM sTrans = jlong_to_ptr(ID);

    if (sTrans == NULL) {
        J2dRlsTraceLn(J2D_TRACE_ERROR, "LCMS_colorConvert: transform == NULL");
        JNU_ThrowByName(env, "java/awt/color/CMMException",
                        "Cannot get color transform");
        return;
    }

    void *inputBuffer = getILData(env, srcData, srcDType);
    if (inputBuffer == NULL) {
        J2dRlsTraceLn(J2D_TRACE_ERROR, "");
        // An exception should have already been thrown.
        return;
    }

    void *outputBuffer = getILData(env, dstData, dstDType);
    if (outputBuffer == NULL) {
        releaseILData(env, inputBuffer, srcDType, srcData, JNI_ABORT);
        // An exception should have already been thrown.
        return;
    }

    char *input = (char *) inputBuffer + srcOffset;
    char *output = (char *) outputBuffer + dstOffset;

    cmsDoTransformLineStride(sTrans, input, output, width, height,
                             srcNextRowOffset, dstNextRowOffset, 0, 0);

    releaseILData(env, inputBuffer, srcDType, srcData, JNI_ABORT);
    releaseILData(env, outputBuffer, dstDType, dstData, 0);
}

static cmsBool _getHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize)
{
  cmsUInt32Number pfSize = 0;
  cmsUInt8Number* pfBuffer = NULL;
  cmsBool status = FALSE;

  if (!cmsSaveProfileToMem(pf, NULL, &pfSize) ||
      pfSize < sizeof(cmsICCHeader) ||
      bufferSize < (jint)sizeof(cmsICCHeader))
  {
    return FALSE;
  }

  pfBuffer = malloc(pfSize);
  if (pfBuffer == NULL) {
    return FALSE;
  }

  // load raw profile data into the buffer
  if (cmsSaveProfileToMem(pf, pfBuffer, &pfSize)) {
    memcpy(pBuffer, pfBuffer, sizeof(cmsICCHeader));
    status = TRUE;
  }
  free(pfBuffer);
  return status;
}

static cmsBool _setHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize)
{
  cmsICCHeader pfHeader;

  if (pBuffer == NULL || bufferSize < (jint)sizeof(cmsICCHeader)) {
    return FALSE;
  }

  memcpy(&pfHeader, pBuffer, sizeof(cmsICCHeader));

  // now set header fields, which we can access using the lcms2 public API
  cmsSetHeaderFlags(pf, _cmsAdjustEndianess32(pfHeader.flags));
  cmsSetHeaderManufacturer(pf, _cmsAdjustEndianess32(pfHeader.manufacturer));
  cmsSetHeaderModel(pf, _cmsAdjustEndianess32(pfHeader.model));
  cmsUInt64Number attributes;
  _cmsAdjustEndianess64(&attributes, &pfHeader.attributes);
  cmsSetHeaderAttributes(pf, attributes);
  cmsSetHeaderProfileID(pf, (cmsUInt8Number*)&(pfHeader.profileID));
  cmsSetHeaderRenderingIntent(pf, _cmsAdjustEndianess32(pfHeader.renderingIntent));
  cmsSetPCS(pf, _cmsAdjustEndianess32(pfHeader.pcs));
  cmsSetColorSpace(pf, _cmsAdjustEndianess32(pfHeader.colorSpace));
  cmsSetDeviceClass(pf, _cmsAdjustEndianess32(pfHeader.deviceClass));
  cmsSetEncodedICCversion(pf, _cmsAdjustEndianess32(pfHeader.version));

  return TRUE;
}

/* Returns new profile handler, if it was created successfully,
   NULL otherwise.
   */
static cmsHPROFILE _writeCookedTag(const cmsHPROFILE pfTarget,
                               const cmsTagSignature sig,
                               jbyte *pData, jint size)
{
    cmsUInt32Number pfSize = 0;
    const cmsInt32Number tagCount = cmsGetTagCount(pfTarget);
    cmsInt32Number i;
    cmsHPROFILE pfSanity = NULL;

    cmsICCHeader hdr;

    cmsHPROFILE p = cmsCreateProfilePlaceholder(NULL);

    if (NULL == p) {
        return NULL;
    }
    memset(&hdr, 0, sizeof(cmsICCHeader));

    // Populate the placeholder's header according to target profile
    hdr.flags = cmsGetHeaderFlags(pfTarget);
    hdr.renderingIntent = cmsGetHeaderRenderingIntent(pfTarget);
    hdr.manufacturer = cmsGetHeaderManufacturer(pfTarget);
    hdr.model = cmsGetHeaderModel(pfTarget);
    hdr.pcs = cmsGetPCS(pfTarget);
    hdr.colorSpace = cmsGetColorSpace(pfTarget);
    hdr.deviceClass = cmsGetDeviceClass(pfTarget);
    hdr.version = cmsGetEncodedICCversion(pfTarget);
    cmsGetHeaderAttributes(pfTarget, &hdr.attributes);
    cmsGetHeaderProfileID(pfTarget, (cmsUInt8Number*)&hdr.profileID);

    cmsSetHeaderFlags(p, hdr.flags);
    cmsSetHeaderManufacturer(p, hdr.manufacturer);
    cmsSetHeaderModel(p, hdr.model);
    cmsSetHeaderAttributes(p, hdr.attributes);
    cmsSetHeaderProfileID(p, (cmsUInt8Number*)&(hdr.profileID));
    cmsSetHeaderRenderingIntent(p, hdr.renderingIntent);
    cmsSetPCS(p, hdr.pcs);
    cmsSetColorSpace(p, hdr.colorSpace);
    cmsSetDeviceClass(p, hdr.deviceClass);
    cmsSetEncodedICCversion(p, hdr.version);

    // now write the user supplied tag
    if (size <= 0 || !cmsWriteRawTag(p, sig, pData, size)) {
        cmsCloseProfile(p);
        return NULL;
    }

    // copy tags from the original profile
    for (i = 0; i < tagCount; i++) {
        cmsBool isTagReady = FALSE;
        const cmsTagSignature s = cmsGetTagSignature(pfTarget, i);
        const cmsUInt32Number tagSize = cmsReadRawTag(pfTarget, s, NULL, 0);

        if (s == sig) {
            // skip the user supplied tag
            continue;
        }

        // read raw tag from the original profile
        if (tagSize > 0) {
            cmsUInt8Number* buf = (cmsUInt8Number*)malloc(tagSize);
            if (buf != NULL) {
                if (tagSize ==  cmsReadRawTag(pfTarget, s, buf, tagSize)) {
                    // now we are ready to write the tag
                    isTagReady = cmsWriteRawTag(p, s, buf, tagSize);
                }
                free(buf);
            }
        }

        if (!isTagReady) {
            cmsCloseProfile(p);
            return NULL;
        }
    }

    // now we have all tags moved to the new profile.
    // do some sanity checks: write it to a memory buffer and read again.
    void* buf = NULL;
    if (cmsSaveProfileToMem(p, NULL, &pfSize)) {
        buf = malloc(pfSize);
        if (buf != NULL) {
            // load raw profile data into the buffer
            if (cmsSaveProfileToMem(p, buf, &pfSize)) {
                pfSanity = cmsOpenProfileFromMem(buf, pfSize);
            }
        }
    }

    cmsCloseProfile(p); // No longer needed.

    if (pfSanity == NULL) {
        // for some reason, we failed to save and read the updated profile
        // It likely indicates that the profile is not correct, so we report
        // a failure here.
        free(buf);
        return NULL;
    } else {
        // do final check whether we can read and handle the target tag.
        const void* pTag = cmsReadTag(pfSanity, sig);
        if (pTag == NULL) {
            // the tag can not be cooked
            free(buf);
            cmsCloseProfile(pfSanity);
            return NULL;
        }
        // The profile we used for sanity checking needs to be returned
        // since the one we updated is raw - not cooked.
        // Except we want to re-open it since the call to cmsReadTag()
        // means we may not get back the same bytes as we set.
        // Whilst this may change later anyway, we can at least prevent
        // it from happening immediately.
        cmsCloseProfile(pfSanity);
        pfSanity = cmsOpenProfileFromMem(buf, pfSize);
        free(buf);
        return pfSanity;
    }
}
