Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Non-accurate color when using local file icon #24

Open
veler opened this issue Aug 23, 2020 · 3 comments
Open

Non-accurate color when using local file icon #24

veler opened this issue Aug 23, 2020 · 3 comments
Labels
bug Something isn't working

Comments

@veler
Copy link
Owner

veler commented Aug 23, 2020

Describe the bug
Using the following image as an icon will transform the blue of the sky to orange.

118286595_307653033658675_4718015689046483648_n

image

Additional context

It's probably due to some sort of encodage.

@veler veler added the bug Something isn't working label Aug 23, 2020
@Web-cloud-warrior
Copy link

The problem appears to be in the FromStream extension, I suspect FromStream passes non-palette pngs' pixels unswizzled. The serialisation provider's WritableBitmapToBase64Async is looking for RgBa8, FromStream is clearly BgR8 for the blue and red to swap.

Replace the following in the IconService.cs to fix this bug

   public async Task<string> PickUpIconFromLocalFileAsync(CancellationToken cancellationToken)
    {
        return await TaskHelper.RunOnUIThreadAsync(async () =>
        {
            try
            {
                var fileOpenPicker = new Windows.Storage.Pickers.FileOpenPicker
                {
                    ViewMode = Windows.Storage.Pickers.PickerViewMode.List,
                    SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.PicturesLibrary
                };
                fileOpenPicker.FileTypeFilter.Add(".jpg");
                fileOpenPicker.FileTypeFilter.Add(".jpeg");
                fileOpenPicker.FileTypeFilter.Add(".png");
                fileOpenPicker.FileTypeFilter.Add(".bmp");

                StorageFile storageFile = await fileOpenPicker.PickSingleFileAsync();
                if (storageFile != null)
                {
                    // Read the retrieved image's bytes and write them into an IRandomAccessStream
                    IRandomAccessStream  stream = await storageFile.OpenAsync(FileAccessMode.Read);
                    IBuffer buffer = new Windows.Storage.Streams.Buffer((uint)stream.Size);
                    await stream.ReadAsync(buffer, (uint)stream.Size, InputStreamOptions.None);
                    InMemoryRandomAccessStream randomAccessStream = new InMemoryRandomAccessStream();
                    await randomAccessStream.WriteAsync(buffer);

                    // Decode the image (with premultiplied alpha) as Rgba8 not the streams Bgra8
                    // GetPixelDataAsync lets us pass in the desired format and it'll do the magic to translate as it decodes
                    BitmapDecoder decoder = await BitmapDecoder.CreateAsync(randomAccessStream);
                    var pixelData = await decoder.GetPixelDataAsync(BitmapPixelFormat.Rgba8, BitmapAlphaMode.Premultiplied, new BitmapTransform(), ExifOrientationMode.IgnoreExifOrientation, ColorManagementMode.DoNotColorManage);

                    // Get the decoded bytes
                    byte[] imageData = pixelData.DetachPixelData();

                    // And stick them in a WriteableBitmap
                    WriteableBitmap image = new WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight);
                    Stream pixelStream = image.PixelBuffer.AsStream();

                    pixelStream.Seek(0, SeekOrigin.Begin);
                    pixelStream.Write(imageData, 0, imageData.Length);

                    if (image.PixelWidth > Constants.AccountIconSize + 50)
                    {
                        // If we judge the image is too big, we resize it. This improves the image quality because the resize is bilinear,
                        // and it reduce the size of the user data bundle file.
                        double propotion = image.PixelWidth / (double)image.PixelHeight;
                        image = image.Resize(
                            (int)Constants.AccountIconSize,
                            (int)(Constants.AccountIconSize / propotion),
                            WriteableBitmapExtensions.Interpolation.Bilinear);
                    }
                    return await _serializationProvider.WritableBitmapToBase64Async(image, cancellationToken).ConfigureAwait(true);
           
                }
            }
            catch (OperationCanceledException) { }
            catch (Exception ex)
            {
                _logger.LogFault(PickUpIconFromLocalFileAsyncFaultEvent, $"Unable to open an image file.", ex);
            }

            return string.Empty;
        }).ConfigureAwait(false);
    }

@veler
Copy link
Owner Author

veler commented Aug 5, 2021

Hi,

Thank you so much for this! Feel free to open a Pull Request if you want to contribute to it, or I can make one this weekend probably :)

@Web-cloud-warrior
Copy link

Hi,

Your welcome on the fix, as I am in the middle of a few things can I get you to apply the fix if you are happy with it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants