Skip to content

Add ICO and CUR file decoder.#2579

Merged
JimBobSquarePants merged 29 commits into
SixLabors:mainfrom
frg2089:feat/icon
Jun 19, 2024
Merged

Add ICO and CUR file decoder.#2579
JimBobSquarePants merged 29 commits into
SixLabors:mainfrom
frg2089:feat/icon

Conversation

@frg2089
Copy link
Copy Markdown
Contributor

@frg2089 frg2089 commented Nov 8, 2023

Prerequisites

  • I have written a descriptive pull-request title
  • I have verified that there are no overlapping pull-requests open
  • I have verified that I am following the existing coding patterns and practice as demonstrated in the repository. These follow strict Stylecop rules 👮.
  • I have provided test coverage for my change (where applicable)

Description

  • Make the Bmp Decoder Core to support ICO's data.
  • 🎉 Add ICO Encoder.
  • Add ICO Decoder.
  • Add ICO Image Format Detector.
  • 🎉 Add CUR Encoder.
  • Add CUR Decoder.
  • Add CUR Image Format Detector.

Some Questions

Warning

We don't support bmp palettes yet.

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Nov 8, 2023

CLA assistant check
All committers have signed the CLA.

@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@Poker-sang
Copy link
Copy Markdown
Contributor

Poker-sang commented Nov 8, 2023

Even though there is no magic head for ICOs, should we still provide IcoImageFormatDetector as well? In order to support Image.Load<TPixel>().

And should we name the classes with Ico instead of Icon?

Comment thread src/ImageSharp/Image.cs Outdated
@JimBobSquarePants
Copy link
Copy Markdown
Member

Even though there is no magic head for ICOs, should we still provide IcoImageFormatDetector as well? In order to support Image.Load<TPixel>().

And should we name the classes with Ico instead of Icon?

How do you identify without leading bytes?

@Poker-sang
Copy link
Copy Markdown
Contributor

Poker-sang commented Nov 8, 2023

Maybe we can combine an ICODir and an entry, and think of it as the header of an ICO file.

Or we just provide a decoder, but this decoder will not be used without specification.

@frg2089
Copy link
Copy Markdown
Contributor Author

frg2089 commented Nov 8, 2023

Maybe we can combine an ICODir and an entry, and think of it as the header of an ICO file.

Or we just provide a decoder, but this decoder will not be used without specification.

I think we can do without providing IconImageFormatDetector.
Because nobody cares if unknown streams are ICOs. They are usually not transmitted without filename.
So we should just provide a decoder and use it directly.

like this

using SixLabors.ImageSharp.Formats.Icon;

async using var fs = File.OpenRead(@"xxx.ico");
var ico = IconDecoder.Instance.Decode(new (), fs);

@frg2089 frg2089 marked this pull request as draft November 8, 2023 12:43
@frg2089 frg2089 force-pushed the feat/icon branch 2 times, most recently from 6f211c1 to a70c1ca Compare November 9, 2023 14:47
@frg2089 frg2089 marked this pull request as ready for review November 9, 2023 14:50
@Poker-sang
Copy link
Copy Markdown
Contributor

Poker-sang commented Nov 9, 2023

We actually have an open discussion supporting tiffs with multisize frames. It would be good to split any changes to the tiff decoder out so we can draw the pixel data on the frame.

@JimBobSquarePants Yes. I have reverted all changes to tiff files.

@frg2089 frg2089 marked this pull request as draft November 10, 2023 13:47
@frg2089 frg2089 marked this pull request as ready for review November 10, 2023 14:30
Copy link
Copy Markdown
Member

@JimBobSquarePants JimBobSquarePants left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this, your efforts are really appreciated! There's a lot to discuss.

Some notes...

I don't think it's a good idea to merge the two formats. We're creating unnecessary ambiguity. If you look at format metadata, we avoid exposing unconstrained configuration values.

It's imperative that the pixel data is drawn on the frame and not resized. Position 0,0, seems sane as an origin. Any other behavior such as resizing or introducing new image types or editing existing signifies a major breaking change for the library.

We need an encoder. I can't accept code against main without one as we need to ensure that we have covered encoding requirements in the format design.

I'll be honest and say this won't get merged before V4. There's a lot to do to ensure that the decoder is safe (I haven't checked bounds handling and EOF detection) and the design practical.

Comment thread src/ImageSharp/Formats/Ico/IcoConfigurationModule.cs Outdated
Comment thread src/ImageSharp/Formats/Ico/IcoConstants.cs Outdated
Comment thread src/ImageSharp/Formats/Ico/IcoDecoderCore.cs Outdated
Comment thread src/ImageSharp/Formats/Ico/IcoDecoderCore.cs Outdated
Comment thread src/ImageSharp/Formats/Ico/IcoFrameMetadata.cs Outdated
Comment thread src/ImageSharp/Formats/Ico/IcoFrameMetadata.cs Outdated
Comment thread src/ImageSharp/Formats/Ico/IcoFrameMetadata.cs Outdated
Comment thread src/ImageSharp/Formats/Ico/IcoMetadata.cs Outdated
Comment thread src/ImageSharp/Formats/Ico/IcoMetadata.cs Outdated
Comment thread src/ImageSharp/Formats/Ico/IcoMetadata.cs Outdated
@frg2089 frg2089 marked this pull request as draft November 11, 2023 06:09
Copy link
Copy Markdown
Member

@JimBobSquarePants JimBobSquarePants left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You've gone the opposite direction to how I hoped I'm afraid here. Please let me know if you need further guidance and I'll try my best to explain.

Comment thread .gitattributes
Comment thread src/ImageSharp/Formats/Bmp/BmpDecoderOptions.cs Outdated
Comment thread src/ImageSharp/Formats/Bmp/BmpMetadata.cs Outdated
Comment thread src/ImageSharp/Formats/Cur/CurBmpFrameMetadata.cs Outdated
Comment thread src/ImageSharp/Formats/Ico/Common/IcoLikeDecoderCore.cs Outdated
Comment thread src/ImageSharp/Formats/Ico/Common/IcoLikeFrameCompression.cs Outdated
Comment thread src/ImageSharp/Formats/Ico/Common/IcoLikeFrameMetadata.cs Outdated
Comment thread src/ImageSharp/Formats/Ico/IcoBmpFrameMetadata.cs Outdated
Comment thread src/ImageSharp/Formats/Ico/IcoImageFormatDetector.cs Outdated
Comment thread src/ImageSharp/Formats/Ico/IcoPngFrameMetadata.cs Outdated
@frg2089
Copy link
Copy Markdown
Contributor Author

frg2089 commented Nov 13, 2023

You've gone the opposite direction to how I hoped I'm afraid here. Please let me know if you need further guidance and I'll try my best to explain.

I refactored the code.
Now it doesn't have the IcoPngFrameMetadata, IcoBmpFrameMetadata and the corresponding Cur variants.
We can use GetFormatMetadata(XXXFormat.Instance) (which isn't there yet) to get specific metadata.
If I'm not doing this the right way, I'm probably not understanding what you're really thinking.

@JimBobSquarePants
Copy link
Copy Markdown
Member

JimBobSquarePants commented Nov 13, 2023

I'm going to write some code to your fork....

OK. So, I've refactored the base decoder to be more efficient and allow us to gather the correct metadata from the png/bmp frames.

I've added a bunch of TODOs in the code also. Please let me know if anything is not clear.

Copy link
Copy Markdown
Contributor Author

@frg2089 frg2089 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have some questions about how to store PngMetadata and BmpMetadata.

We should store BitsPerPixel property for encoder.
The ICO file may have more than one PNG data.

Comment thread src/ImageSharp/Formats/Icon/IconDecoderCore.cs Outdated
Comment on lines +106 to +102
if (bmpMetadata != null)
{
result.Metadata.SetFormatMetadata(BmpFormat.Instance, bmpMetadata);
}

if (pngMetadata != null)
{
result.Metadata.SetFormatMetadata(PngFormat.Instance, pngMetadata);
}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the PNG data may not be the only one. ICO file may have 2 and more PNG data.
So, we should store the PngMetadata in the FrameMetadata instead of the ImageMetadata.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They’re just for easy conversation really. See below re bits per pixel. You may want to capture palette data also

@JimBobSquarePants
Copy link
Copy Markdown
Member

I have some questions about how to store PngMetadata and BmpMetadata.

We should store BitsPerPixel property for encoder. The ICO file may have more than one PNG data.

I’d store that in the Ico/Cur frame metadata. I’d make it an enum though (it’s a fixed range based on available bmp/png fixes)

@JimBobSquarePants
Copy link
Copy Markdown
Member

Apologies for the radio silence over the last few weeks. I've been very busy fixing up the animation behavior for v3.1

@frg2089
Copy link
Copy Markdown
Contributor Author

frg2089 commented Dec 14, 2023

Do we have some new ways to save frames of different sizes yet?

@JimBobSquarePants
Copy link
Copy Markdown
Member

Do we have some new ways to save frames of different sizes yet?

You encode the size stored in the metadata. Pixel buffers can be constrained to regions


protected IconDir FileHeader { get => this.fileHeader; private set => this.fileHeader = value; }

protected IconDirEntry[] Entries { get; private set; } = [];
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SA1010
Should I avoid this syntax?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should be fine now that I've updated the StyleCop version.

@frg2089 frg2089 marked this pull request as ready for review December 14, 2023 15:02
This was referenced May 12, 2026
WarperSan added a commit to WarperSan/ThunderPipe that referenced this pull request May 15, 2026
Updated [SixLabors.ImageSharp](https://github.com/SixLabors/ImageSharp)
from 3.1.12 to 4.0.0.

<details>
<summary>Release notes</summary>

_Sourced from [SixLabors.ImageSharp's
releases](https://github.com/SixLabors/ImageSharp/releases)._

## 4.0.0

## What's Changed
* Update to net8 by @​stefannikolei in
SixLabors/ImageSharp#2583
* Handle dedup of local palette of 256 length - Main by
@​JimBobSquarePants in SixLabors/ImageSharp#2607
* Replace custom Crc32 by @​JimBobSquarePants in
SixLabors/ImageSharp#2611
* Sync 3.1 DrawImage fixes by @​tocsoft in
SixLabors/ImageSharp#2612
* Fix handling gif encoding for global palettes - Main by
@​JimBobSquarePants in SixLabors/ImageSharp#2615
* Bump actions/setup-dotnet from 3 to 4 by @​dependabot[bot] in
SixLabors/ImageSharp#2613
* Adjusted the casing of the Webp format name by @​jscarle in
SixLabors/ImageSharp#2623
* Fix Paeth Filter decode on platforms that do not support Ssse3 - Main
by @​JimBobSquarePants in
SixLabors/ImageSharp#2620
* Fix WebP animation speed bug by @​marklagendijk in
SixLabors/ImageSharp#2624
* Promote PixelTypeInfo to Pixel by @​stefannikolei in
SixLabors/ImageSharp#2601
* TGA: Treat 32 bit True Color images always as transparent by
@​brianpopow in SixLabors/ImageSharp#2643
* Modernize and optimize pixel format operations across platforms. by
@​JimBobSquarePants in SixLabors/ImageSharp#2645
* Cleanup SimdUtils by @​JimBobSquarePants in
SixLabors/ImageSharp#2654
* Bump actions/cache from 3 to 4 by @​dependabot[bot] in
SixLabors/ImageSharp#2648
* Bump codecov/codecov-action from 3 to 4 by @​dependabot[bot] in
SixLabors/ImageSharp#2657
* Bump NuGet/setup-nuget from 1 to 2 by @​dependabot[bot] in
SixLabors/ImageSharp#2658
* Add v3.1.x fixes #​2673 and #​2674 into main. by @​JimBobSquarePants
in SixLabors/ImageSharp#2675
* Add fixes 2668, 2676, and 2677 to main by @​JimBobSquarePants in
SixLabors/ImageSharp#2678
* Merge 2681 to v4 Main by @​JimBobSquarePants in
SixLabors/ImageSharp#2690
* Add JPEG COM marker support by @​RobertMut in
SixLabors/ImageSharp#2641
* Bump actions/upload-artifact from 3 to 4 by @​dependabot[bot] in
SixLabors/ImageSharp#2625
* Only exit JPEG scan decoding after multiple EOF hits by
@​JimBobSquarePants in SixLabors/ImageSharp#2701
* V4 Ensure VP8X alpha flag is updated correctly. by @​JimBobSquarePants
in SixLabors/ImageSharp#2703
* Fix animated png handling (issue #​2708) by @​SpaceCheetah in
SixLabors/ImageSharp#2710
* Merge latest release from v3 by @​JimBobSquarePants in
SixLabors/ImageSharp#2720
* Fix MacOS jobs by @​antonfirsov in
SixLabors/ImageSharp#2728
* Fix async-over-sync issue in Image.DecodeAsync() by @​kroymann in
SixLabors/ImageSharp#2725
* Fix overflow in MemoryAllocator.Create(options) by @​antonfirsov in
SixLabors/ImageSharp#2730
* GifDecoder: Limit lzw bits to a maximum of 12 bits by @​brianpopow in
SixLabors/ImageSharp#2744
* GifDecoder : Allow skipping bad metadata using identify by
@​JimBobSquarePants in SixLabors/ImageSharp#2749
* Add ICO and CUR file decoder. by @​frg2089 in
SixLabors/ImageSharp#2579
* v4 - Fix off-by-one error when centering a transform. by
@​JimBobSquarePants in SixLabors/ImageSharp#2761
* v4 Fix 2758 by @​JimBobSquarePants in
SixLabors/ImageSharp#2764
* Simplify Color Space Conversion APIs by @​JimBobSquarePants in
SixLabors/ImageSharp#2739
* Webp: Fix Issue 2763 by @​brianpopow in
SixLabors/ImageSharp#2767
* V4 Correctly break during Png decoding by @​JimBobSquarePants in
SixLabors/ImageSharp#2773
* V4 : Fix filtering on PNG encode. by @​JimBobSquarePants in
SixLabors/ImageSharp#2778
* Fix #​2779 buffer overrun by @​KirillAldashkin in
SixLabors/ImageSharp#2780
* Fix ImageMetadata docs typo by @​lofcz in
SixLabors/ImageSharp#2781
* Add API for metadata conversion between formats. by
@​JimBobSquarePants in SixLabors/ImageSharp#2751
* Tiff decoder: Fix issue 2679 by @​brianpopow in
SixLabors/ImageSharp#2789
* Replace PngCrcChunkHandling by @​JimBobSquarePants in
SixLabors/ImageSharp#2786
* Add tagname to debugger visualization for Exif- and Iptc-values, to
facilitate easier debugging and discovery by @​lassevk in
SixLabors/ImageSharp#2787
* V4 - Correctly handle transform spaces when building transform
matrices. by @​JimBobSquarePants in
SixLabors/ImageSharp#2795
* Allow decoding Tiff of different frame size. by @​JimBobSquarePants in
SixLabors/ImageSharp#2788
* Add progressive JPEG encoder by @​ardabada in
SixLabors/ImageSharp#2740
* Fix using dither in BmpEncoder when bit per pixel is <= 4 by @​mistoll
in SixLabors/ImageSharp#2819
* Add QuadDistortion to ProjectiveTransformBuilder by @​Socolin in
SixLabors/ImageSharp#2748
* WEBP : Use Correct Width With AlphaDecoder by @​JimBobSquarePants in
SixLabors/ImageSharp#2823
 ... (truncated)

Commits viewable in [compare
view](SixLabors/ImageSharp@v3.1.12...v4.0.0).
</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: WarperSan <leumas.ecole@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants