Ejemplo n.º 1
0
        private void FromStream(Stream stm, string filename)
        {
            Debug.Assert(stm != null);

            int bufferSize = _bufferSizeIncrement;

            if (stm.CanSeek)
            {
                bufferSize = (int)stm.Length + 1; // If this stream is seekable (most cases), we will only have one buffer alloc and read below
                                                  // otherwise, we will incrementally grow the buffer and read until end of profile.
                                                  // profiles are typcially small, so usually one allocation will suffice
            }

            byte[] rawBytes     = new byte[bufferSize];
            int    numBytesRead = 0;

            while (bufferSize < _maximumColorContextLength)
            {
                numBytesRead += stm.Read(rawBytes, numBytesRead, bufferSize - numBytesRead);

                if (numBytesRead < bufferSize)
                {
                    FromRawBytes(rawBytes, numBytesRead, /* dontThrowException = */ false);

                    using (FactoryMaker factoryMaker = new FactoryMaker())
                    {
                        HRESULT.Check(UnsafeNativeMethodsMilCoreApi.WICCodec.CreateColorContext(factoryMaker.ImagingFactoryPtr, out _colorContextHandle));
                        HRESULT.Check(IWICCC.InitializeFromMemory(_colorContextHandle, rawBytes, (uint)numBytesRead));
                    }

                    return;
                }
                else
                {
                    bufferSize += _bufferSizeIncrement;
                    byte[] newRawBytes = new byte[bufferSize];
                    rawBytes.CopyTo(newRawBytes, 0);
                    rawBytes = newRawBytes;
                }
            }

            throw new ArgumentException(SR.Get(SRID.ColorContext_FileTooLarge), filename);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Create a ColorContext from an unmanaged color context
        /// </summary>
        private ColorContext(SafeMILHandle colorContextHandle)
        {
            _colorContextHandle = colorContextHandle;

            //
            // For 3.* backwards compat, we aren't going to HRESULT.Check() anywhere because
            // that could introduce new exceptions. If anything fails, _colorContextHelper
            // will be invalid and we'll emulate the old failure behavior later in
            // OpenProfileStream()
            //

            IWICCC.WICColorContextType type;
            if (HRESULT.Failed(IWICCC.GetType(_colorContextHandle, out type)))
            {
                return;
            }

            switch (type)
            {
            case IWICCC.WICColorContextType.WICColorContextProfile:
                uint cbProfileActual;
                int  hr = IWICCC.GetProfileBytes(_colorContextHandle, 0, null, out cbProfileActual);
                if (HRESULT.Succeeded(hr) && cbProfileActual != 0)
                {
                    byte[] profileData = new byte[cbProfileActual];
                    if (HRESULT.Failed(IWICCC.GetProfileBytes(
                                           _colorContextHandle, cbProfileActual, profileData, out cbProfileActual))
                        )
                    {
                        return;
                    }

                    FromRawBytes(profileData, (int)cbProfileActual, /* dontThrowException = */ true);
                }

                break;

            case IWICCC.WICColorContextType.WICColorContextExifColorSpace:
                uint colorSpace;
                if (HRESULT.Failed(IWICCC.GetExifColorSpace(_colorContextHandle, out colorSpace)))
                {
                    return;
                }

                //
                // From MSDN:
                //     "1" is sRGB. We will use our built-in sRGB profile.
                //     "2" is Adobe RGB. WIC says we should never see this because they are nonstandard and instead a
                //     real profile will be returned.
                //     "3-65534" is unused.
                //
                // From the Exif spec:
                //     B. Tag Relating to Color Space
                //     ColorSpace
                //
                //     The color space information tag (ColorSpace) is always recorded as the color space specifier.
                //     Normally sRGB (=1) is used to define the color space based on the PC monitor conditions and environment. If a
                //     color space other than sRGB is used, Uncalibrated (=FFFF.H) is set. Image data recorded as Uncalibrated can be
                //     treated as sRGB when it is converted to Flashpix. On sRGB see Annex E.
                //     Tag = 40961 (A001.H)
                //     Type = SHORT
                //     Count = 1
                //     1 = sRGB
                //     FFFF.H = Uncalibrated
                //
                // So for 65535 we will return sRGB since it is acceptible rather than having an invalid ColorContext. The Exif
                // CC should always be the second one so the real one is given priority. Alternatively, we could ignore the
                // uncalibrated CC but that would be a breaking change with 3.* (returning 1 instead of 2).
                //
                // If anything other than 1 or 65535 happens, _colorContextHelper will remain invalid and we will emulate
                // the old crash behavior in OpenProfileStream().
                //

                if (colorSpace == 1 || colorSpace == 65535)
                {
                    ResourceManager resourceManager = new ResourceManager(
                        _colorProfileResources, Assembly.GetAssembly(typeof(ColorContext))
                        );
                    byte[] sRGBProfile = (byte[])resourceManager.GetObject(_sRGBProfileName);
                    // The existing ColorContext has already been initialized as Exif so we can't initialize it again
                    // and instead must create a new one.
                    using (FactoryMaker factoryMaker = new FactoryMaker())
                    {
                        _colorContextHandle.Dispose();
                        _colorContextHandle = null;

                        if (HRESULT.Failed(UnsafeNativeMethodsMilCoreApi.WICCodec.CreateColorContext(
                                               factoryMaker.ImagingFactoryPtr, out _colorContextHandle))
                            )
                        {
                            return;
                        }

                        if (HRESULT.Failed(IWICCC.InitializeFromMemory(
                                               _colorContextHandle, sRGBProfile, (uint)sRGBProfile.Length))
                            )
                        {
                            return;
                        }
                    }

                    // Finally, fill in _colorContextHelper
                    FromRawBytes(sRGBProfile, sRGBProfile.Length, /* dontThrowException = */ true);
                }
                else if (Invariant.Strict)
                {
                    Invariant.Assert(false, String.Format(CultureInfo.InvariantCulture, "IWICColorContext::GetExifColorSpace returned {0}.", colorSpace));
                }

                break;

            default:
                if (Invariant.Strict)
                {
                    Invariant.Assert(false, "IWICColorContext::GetType() returned WICColorContextUninitialized.");
                }

                break;
            }


            // SECURITY NOTE: This constructor does not set a Uri because the profile comes from raw file
            //                data. Thus, we don't set _isProfileUriNotFromUser to true because we
            //                don't want get_ProfileUri to demand permission to return null.
            Debug.Assert(_profileUri.Value == null);
        }