PaZword icon indicating copy to clipboard operation
PaZword copied to clipboard

Non-accurate color when using local file icon

Open veler opened this issue 3 years ago • 3 comments

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 avatar Aug 23 '20 21:08 veler

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);
    }

Web-cloud-warrior avatar Aug 05 '21 00:08 Web-cloud-warrior

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 :)

veler avatar Aug 05 '21 01:08 veler

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.

Web-cloud-warrior avatar Aug 05 '21 22:08 Web-cloud-warrior