void createColorTransform(const ColorProfile& colorProfile, bool hasAlpha, bool sRGB)
    {
        clearColorTransform();

        if (colorProfile.isEmpty() && !sRGB)
            return;
        qcms_profile* deviceProfile = ImageDecoder::qcmsOutputDeviceProfile();
        if (!deviceProfile)
            return;
        qcms_profile* inputProfile = 0;
        if (!colorProfile.isEmpty())
            inputProfile = qcms_profile_from_memory(colorProfile.data(), colorProfile.size());
        else
            inputProfile = qcms_profile_sRGB();
        if (!inputProfile)
            return;

        // We currently only support color profiles for RGB and RGBA images.
        ASSERT(rgbData == qcms_profile_get_color_space(inputProfile));

        if (qcms_profile_match(inputProfile, deviceProfile)) {
            qcms_profile_release(inputProfile);
            return;
        }

        // FIXME: Don't force perceptual intent if the image profile contains an intent.
        qcms_data_type dataFormat = hasAlpha ? QCMS_DATA_RGBA_8 : QCMS_DATA_RGB_8;
        m_transform = qcms_transform_create(inputProfile, dataFormat, deviceProfile, dataFormat, QCMS_INTENT_PERCEPTUAL);

        qcms_profile_release(inputProfile);
    }
Example #2
0
TESTFUNC_TYPE
LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
  qcms_enable_iccv4();

  qcms_profile* profile = qcms_profile_from_memory(data, size);
  if (!profile) {
    return 0;
  }

  qcms_profile* srgb_profile = qcms_profile_sRGB();
  if (!srgb_profile) {
    qcms_profile_release(profile);
    return 0;
  }

  transform(profile, srgb_profile, size);

  // Firefox only checks the display (destination) profile.
  if (qcms_profile_is_bogus(profile)) {
    goto release_profiles;
  };

  transform(srgb_profile, profile, size);

release_profiles:
  qcms_profile_release(profile);
  qcms_profile_release(srgb_profile);

  return 0;
}
Example #3
0
/* Shuts down various transforms and profiles for CMS. */
static void ShutdownCMS()
{

    if (gCMSRGBTransform) {
        qcms_transform_release(gCMSRGBTransform);
        gCMSRGBTransform = nsnull;
    }
    if (gCMSInverseRGBTransform) {
        qcms_transform_release(gCMSInverseRGBTransform);
        gCMSInverseRGBTransform = nsnull;
    }
    if (gCMSRGBATransform) {
        qcms_transform_release(gCMSRGBATransform);
        gCMSRGBATransform = nsnull;
    }
    if (gCMSOutputProfile) {
        qcms_profile_release(gCMSOutputProfile);

        // handle the aliased case
        if (gCMSsRGBProfile == gCMSOutputProfile)
            gCMSsRGBProfile = nsnull;
        gCMSOutputProfile = nsnull;
    }
    if (gCMSsRGBProfile) {
        qcms_profile_release(gCMSsRGBProfile);
        gCMSsRGBProfile = nsnull;
    }

    // Reset the state variables
    gCMSIntent = -2;
    gCMSMode = eCMSMode_Off;
    gCMSInitialized = PR_FALSE;
}
Example #4
0
// -----------------------------------------------------------------------------
// Color profile handling
static int ApplyColorProfile(const WebPData* const profile,
                             WebPDecBuffer* const rgba) {
#ifdef WEBP_HAVE_QCMS
  int i, ok = 0;
  uint8_t* line;
  uint8_t major_revision;
  qcms_profile* input_profile = NULL;
  qcms_profile* output_profile = NULL;
  qcms_transform* transform = NULL;
  const qcms_data_type input_type = QCMS_DATA_RGBA_8;
  const qcms_data_type output_type = QCMS_DATA_RGBA_8;
  const qcms_intent intent = QCMS_INTENT_DEFAULT;

  if (profile == NULL || rgba == NULL) return 0;
  if (profile->bytes == NULL || profile->size < 10) return 1;
  major_revision = profile->bytes[8];

  qcms_enable_iccv4();
  input_profile = qcms_profile_from_memory(profile->bytes, profile->size);
  // qcms_profile_is_bogus() is broken with ICCv4.
  if (input_profile == NULL ||
      (major_revision < 4 && qcms_profile_is_bogus(input_profile))) {
    fprintf(stderr, "Color profile is bogus!\n");
    goto Error;
  }

  output_profile = qcms_profile_sRGB();
  if (output_profile == NULL) {
    fprintf(stderr, "Error creating output color profile!\n");
    goto Error;
  }

  qcms_profile_precache_output_transform(output_profile);
  transform = qcms_transform_create(input_profile, input_type,
                                    output_profile, output_type,
                                    intent);
  if (transform == NULL) {
    fprintf(stderr, "Error creating color transform!\n");
    goto Error;
  }

  line = rgba->u.RGBA.rgba;
  for (i = 0; i < rgba->height; ++i, line += rgba->u.RGBA.stride) {
    qcms_transform_data(transform, line, line, rgba->width);
  }
  ok = 1;

 Error:
  if (input_profile != NULL) qcms_profile_release(input_profile);
  if (output_profile != NULL) qcms_profile_release(output_profile);
  if (transform != NULL) qcms_transform_release(transform);
  return ok;
#else
  (void)profile;
  (void)rgba;
  return 1;
#endif  // WEBP_HAVE_QCMS
}
qcms_profile *
gfxPlatform::GetCMSOutputProfile()
{
    if (!gCMSOutputProfile) {
        NS_TIME_FUNCTION;

        nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
        if (prefs) {

            nsresult rv;

            /* Determine if we're using the internal override to force sRGB as
               an output profile for reftests. See Bug 452125.

               Note that we don't normally (outside of tests) set a
               default value of this preference, which means GetBoolPref
               will typically throw (and leave its out-param untouched).
             */
            PRBool doSRGBOverride;
            rv = prefs->GetBoolPref(CMForceSRGBPrefName, &doSRGBOverride);
            if (NS_SUCCEEDED(rv) && doSRGBOverride)
                gCMSOutputProfile = GetCMSsRGBProfile();

            if (!gCMSOutputProfile) {

                nsXPIDLCString fname;
                rv = prefs->GetCharPref(CMProfilePrefName,
                                        getter_Copies(fname));
                if (NS_SUCCEEDED(rv) && !fname.IsEmpty()) {
                    gCMSOutputProfile = qcms_profile_from_path(fname);
                }
            }
        }

        if (!gCMSOutputProfile) {
            gCMSOutputProfile =
                gfxPlatform::GetPlatform()->GetPlatformCMSOutputProfile();
        }

        /* Determine if the profile looks bogus. If so, close the profile
         * and use sRGB instead. See bug 460629, */
        if (gCMSOutputProfile && qcms_profile_is_bogus(gCMSOutputProfile)) {
            NS_ASSERTION(gCMSOutputProfile != GetCMSsRGBProfile(),
                         "Builtin sRGB profile tagged as bogus!!!");
            qcms_profile_release(gCMSOutputProfile);
            gCMSOutputProfile = nsnull;
        }

        if (!gCMSOutputProfile) {
            gCMSOutputProfile = GetCMSsRGBProfile();
        }
        /* Precache the LUT16 Interpolations for the output profile. See 
           bug 444661 for details. */
        qcms_profile_precache_output_transform(gCMSOutputProfile);
    }

    return gCMSOutputProfile;
}
Example #6
0
void do_test(void) {
	unsigned char srct[4] = { 221, 79, 129, 92};
	unsigned char outt[4];
	qcms_transform *transform;
	qcms_profile *input_profile, *output_profile, *rgb;
	qcms_CIE_xyY white_point = { 0, 0, 1.};
	qcms_CIE_xyYTRIPLE primaries = { {.9, .3, 1.}, {.2, .4, 1.}, {.7, .4, 1.}};

	rgb = qcms_profile_create_rgb_with_gamma(white_point, primaries, 1.8);
	input_profile = qcms_profile_sRGB();
	output_profile = qcms_profile_sRGB();
	if (output_profile) {
		test_gray(output_profile);
		test_gray_precache(output_profile);
		qcms_profile_release(output_profile);
	}
	if (input_profile)
		qcms_profile_release(input_profile);
	if (rgb)
		qcms_profile_release(rgb);
	rgb = qcms_profile_from_path("sample-trunc.icc");
	if (rgb)
		qcms_profile_release(rgb);
}
Example #7
0
nsJPEGDecoder::~nsJPEGDecoder()
{
  // Step 8: Release JPEG decompression object
  mInfo.src = nullptr;
  jpeg_destroy_decompress(&mInfo);

  PR_FREEIF(mBackBuffer);
  if (mTransform)
    qcms_transform_release(mTransform);
  if (mInProfile)
    qcms_profile_release(mInProfile);

  PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
         ("nsJPEGDecoder::~nsJPEGDecoder: Destroying JPEG decoder %p",
          this));
}
Example #8
0
void test_gray(qcms_profile *output_profile)
{
	unsigned char srct[3] = { 221, 79, 129};
	unsigned char outt[3];
	qcms_transform *transform;
	qcms_profile *gray_profile = qcms_profile_from_memory(gray_icc, sizeof(gray_icc));
	if (gray_profile) {
		transform = qcms_transform_create(gray_profile, QCMS_DATA_GRAY_8, output_profile, QCMS_DATA_RGB_8, QCMS_INTENT_PERCEPTUAL);
		if (transform) {
			qcms_transform_data(transform, srct, outt, 1);
			qcms_transform_release(transform);
		}
		qcms_profile_release(gray_profile);
	}

}
Example #9
0
nsPNGDecoder::~nsPNGDecoder()
{
  if (mPNG)
    png_destroy_read_struct(&mPNG, mInfo ? &mInfo : nullptr, nullptr);
  if (mCMSLine)
    nsMemory::Free(mCMSLine);
  if (interlacebuf)
    nsMemory::Free(interlacebuf);
  if (mInProfile) {
    qcms_profile_release(mInProfile);

    /* mTransform belongs to us only if mInProfile is non-null */
    if (mTransform)
      qcms_transform_release(mTransform);
  }
}
Example #10
0
nsPNGDecoder::~nsPNGDecoder()
{
  if (mPNG) {
    png_destroy_read_struct(&mPNG, mInfo ? &mInfo : nullptr, nullptr);
  }
  if (mCMSLine) {
    free(mCMSLine);
  }
  if (interlacebuf) {
    free(interlacebuf);
  }
  if (mInProfile) {
    qcms_profile_release(mInProfile);

    // mTransform belongs to us only if mInProfile is non-null
    if (mTransform) {
      qcms_transform_release(mTransform);
    }
  }
}
Example #11
0
    void createColorTransform(const ColorProfile& colorProfile, bool hasAlpha)
    {
        if (m_transform)
            qcms_transform_release(m_transform);
        m_transform = 0;

        if (colorProfile.isEmpty())
            return;
        qcms_profile* deviceProfile = ImageDecoder::qcmsOutputDeviceProfile();
        if (!deviceProfile)
            return;
        qcms_profile* inputProfile = qcms_profile_from_memory(colorProfile.data(), colorProfile.size());
        if (!inputProfile)
            return;
        // We currently only support color profiles for RGB profiled images.
        ASSERT(icSigRgbData == qcms_profile_get_color_space(inputProfile));
        qcms_data_type dataFormat = hasAlpha ? QCMS_DATA_RGBA_8 : QCMS_DATA_RGB_8;
        // FIXME: Don't force perceptual intent if the image profile contains an intent.
        m_transform = qcms_transform_create(inputProfile, dataFormat, deviceProfile, dataFormat, QCMS_INTENT_PERCEPTUAL);
        qcms_profile_release(inputProfile);
    }
bool WEBPImageDecoder::createColorTransform(const char* data, size_t size)
{
    clearColorTransform();

    qcms_profile* deviceProfile = ImageDecoder::qcmsOutputDeviceProfile();
    if (!deviceProfile)
        return false;
    qcms_profile* inputProfile = qcms_profile_from_memory(data, size);
    if (!inputProfile)
        return false;

    // We currently only support color profiles for RGB profiled images.
    ASSERT(icSigRgbData == qcms_profile_get_color_space(inputProfile));
    // The input image pixels are RGBA format.
    qcms_data_type format = QCMS_DATA_RGBA_8;
    // FIXME: Don't force perceptual intent if the image profile contains an intent.
    m_transform = qcms_transform_create(inputProfile, format, deviceProfile, QCMS_DATA_RGBA_8, QCMS_INTENT_PERCEPTUAL);

    qcms_profile_release(inputProfile);
    return !!m_transform;
}
static int qcms_test_internal_srgb(size_t width,
		size_t height,
		int iterations,
		const char *in_path,
		const char *out_path,
		const int force_software)
{
	qcms_profile *profile = qcms_profile_sRGB();
	s15Fixed16Number sRGB_internal[3][3];
	s15Fixed16Number diff = 0;
	int i, j;

	printf("Test qcms internal sRGB colorant matrix against official sRGB IEC61966-2.1 color (D50) primaries\n");

	sRGB_internal[0][0] = profile->redColorant.X;
	sRGB_internal[1][0] = profile->redColorant.Y;
	sRGB_internal[2][0] = profile->redColorant.Z;
	sRGB_internal[0][1] = profile->greenColorant.X;
	sRGB_internal[1][1] = profile->greenColorant.Y;
	sRGB_internal[2][1] = profile->greenColorant.Z;
	sRGB_internal[0][2] = profile->blueColorant.X;
	sRGB_internal[1][2] = profile->blueColorant.Y;
	sRGB_internal[2][2] = profile->blueColorant.Z;

	for (i = 0; i < 3; i++) {
		for (j = 0; j < 3; j++) {
			s15Fixed16Number tmp = sRGB_internal[i][j] - sRGB_reference[i][j];
			printf("\t%d", tmp);
			diff += abs(tmp);
		}
		printf("\n");
	}

	qcms_profile_release(profile);

	printf("Total error = 0x%x [%.6f]\n", diff, diff / 65536.0);

	return diff;
}
Example #14
0
// Adapted from http://www.littlecms.com/pngchrm.c example code
static qcms_profile*
PNGGetColorProfile(png_structp png_ptr, png_infop info_ptr,
                   int color_type, qcms_data_type* inType, uint32_t* intent)
{
  qcms_profile* profile = nullptr;
  *intent = QCMS_INTENT_PERCEPTUAL; // Our default

  // First try to see if iCCP chunk is present
  if (png_get_valid(png_ptr, info_ptr, PNG_INFO_iCCP)) {
    png_uint_32 profileLen;
    png_bytep profileData;
    png_charp profileName;
    int compression;

    png_get_iCCP(png_ptr, info_ptr, &profileName, &compression,
                 &profileData, &profileLen);

    profile = qcms_profile_from_memory((char*)profileData, profileLen);
    if (profile) {
      uint32_t profileSpace = qcms_profile_get_color_space(profile);

      bool mismatch = false;
      if (color_type & PNG_COLOR_MASK_COLOR) {
        if (profileSpace != icSigRgbData) {
          mismatch = true;
        }
      } else {
        if (profileSpace == icSigRgbData) {
          png_set_gray_to_rgb(png_ptr);
        } else if (profileSpace != icSigGrayData) {
          mismatch = true;
        }
      }

      if (mismatch) {
        qcms_profile_release(profile);
        profile = nullptr;
      } else {
        *intent = qcms_profile_get_rendering_intent(profile);
      }
    }
  }

  // Check sRGB chunk
  if (!profile && png_get_valid(png_ptr, info_ptr, PNG_INFO_sRGB)) {
    profile = qcms_profile_sRGB();

    if (profile) {
      int fileIntent;
      png_set_gray_to_rgb(png_ptr);
      png_get_sRGB(png_ptr, info_ptr, &fileIntent);
      uint32_t map[] = { QCMS_INTENT_PERCEPTUAL,
                         QCMS_INTENT_RELATIVE_COLORIMETRIC,
                         QCMS_INTENT_SATURATION,
                         QCMS_INTENT_ABSOLUTE_COLORIMETRIC };
      *intent = map[fileIntent];
    }
  }

  // Check gAMA/cHRM chunks
  if (!profile &&
       png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA) &&
       png_get_valid(png_ptr, info_ptr, PNG_INFO_cHRM)) {
    qcms_CIE_xyYTRIPLE primaries;
    qcms_CIE_xyY whitePoint;

    png_get_cHRM(png_ptr, info_ptr,
                 &whitePoint.x, &whitePoint.y,
                 &primaries.red.x,   &primaries.red.y,
                 &primaries.green.x, &primaries.green.y,
                 &primaries.blue.x,  &primaries.blue.y);
    whitePoint.Y =
      primaries.red.Y = primaries.green.Y = primaries.blue.Y = 1.0;

    double gammaOfFile;

    png_get_gAMA(png_ptr, info_ptr, &gammaOfFile);

    profile = qcms_profile_create_rgb_with_gamma(whitePoint, primaries,
                                                 1.0/gammaOfFile);

    if (profile) {
      png_set_gray_to_rgb(png_ptr);
    }
  }

  if (profile) {
    uint32_t profileSpace = qcms_profile_get_color_space(profile);
    if (profileSpace == icSigGrayData) {
      if (color_type & PNG_COLOR_MASK_ALPHA) {
        *inType = QCMS_DATA_GRAYA_8;
      } else {
        *inType = QCMS_DATA_GRAY_8;
      }
    } else {
      if (color_type & PNG_COLOR_MASK_ALPHA ||
          png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
        *inType = QCMS_DATA_RGBA_8;
      } else {
        *inType = QCMS_DATA_RGB_8;
      }
    }
  }

  return profile;
}