Click here to Skip to main content
15,896,606 members
Articles / Programming Languages / C#

IconLib - Icons Unfolded (MultiIcon and Windows Vista supported)

Rate me:
Please Sign up or sign in to vote.
4.96/5 (671 votes)
14 Feb 2008CC (ASA 2.5)41 min read 1M   15K   661  
Library to manipulate icons and icons libraries with support to create, load, save, import and export icons in ico, icl, dll, exe, cpl and src format. (Windows Vista icons supported).
//  Copyright (c) 2006, Gustavo Franco
//  Email:  gustavo_franco@hotmail.com
//  All rights reserved.

//  Redistribution and use in source and binary forms, with or without modification, 
//  are permitted provided that the following conditions are met:

//  Redistributions of source code must retain the above copyright notice, 
//  this list of conditions and the following disclaimer. 
//  Redistributions in binary form must reproduce the above copyright notice, 
//  this list of conditions and the following disclaimer in the documentation 
//  and/or other materials provided with the distribution. 

//  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
//  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
//  PURPOSE. IT CAN BE DISTRIBUTED FREE OF CHARGE AS LONG AS THIS HEADER 
//  REMAINS UNCHANGED.
using System;
using System.Text;
using System.Diagnostics;
using System.Collections;
using System.Drawing.Imaging;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace System.Drawing.IconLib.ColorProcessing
{
    [Author("Franco, Gustavo")]
    public class FloydSteinbergDithering : IDithering
    {
        #region Variables Declaration
        private const float mOffset16 = 255F / 249F;
        #endregion

        #region Constructors
        public FloydSteinbergDithering()
        {
        }
        #endregion

        #region Methods
        public unsafe void Disperse(byte* pixelSource, int x, int y, byte bpp, int stride, int width, int height, Color colorEntry)
        {
            byte r = 0;
            byte g = 0;
            byte b = 0;
            uint argColor = 0;

            byte* pixelColorComponent;

            GetRGB(pixelSource, bpp, x, ref r, ref g, ref b, ref argColor);
            int errorR = ((int)r) - colorEntry.R; 
            int errorG = ((int)g) - colorEntry.G; 
            int errorB = ((int)b) - colorEntry.B; 

            switch (bpp) 
            {
                case 16:
                    ushort* pixelColorComponentS;
                    if (x + 1 < width) 
                    { 
                        // Right
                        pixelColorComponentS = (ushort*) ((pixelSource) + ((x + 1) * 2));
                        r = (byte) (((*pixelColorComponentS & 0x7C00) >> 7) * mOffset16);
                        g = (byte) (((*pixelColorComponentS & 0x03E0) >> 2) * mOffset16);
                        b = (byte) (((*pixelColorComponentS & 0x001F) << 3) * mOffset16);
                        r = (byte) ((int) ((Limits(r, ((int) (errorR * 7)) >> 4))) & 0xF8); 
                        g = (byte) ((int) ((Limits(g, ((int) (errorG * 7)) >> 4))) & 0xF8); 
                        b = (byte) ((int) ((Limits(b, ((int) (errorB * 7)) >> 4))) & 0xF8); 
                        *pixelColorComponentS = (ushort) (r << 7 | g << 2 | b >> 3);
                    } 
                    if (y + 1 < height) 
                    { 
                        if (x - 1 > 0) 
                        { 
                            // Left and Down
                            pixelColorComponentS = (ushort*) ((pixelSource) + ((x - 1) * 2) + stride);
                            r = (byte) (((*pixelColorComponentS & 0x7C00) >> 7) * mOffset16);
                            g = (byte) (((*pixelColorComponentS & 0x03E0) >> 2) * mOffset16);
                            b = (byte) (((*pixelColorComponentS & 0x001F) << 3) * mOffset16);
                            r = (byte) ((int) ((Limits(r, ((int) (errorR * 3)) >> 4))) & 0xF8); 
                            g = (byte) ((int) ((Limits(g, ((int) (errorG * 3)) >> 4))) & 0xF8); 
                            b = (byte) ((int) ((Limits(b, ((int) (errorB * 3)) >> 4))) & 0xF8); 
                            *pixelColorComponentS = (ushort) (r << 7 | g << 2 | b >> 3);
                        } 

                        // Down
                        pixelColorComponentS = (ushort*) ((pixelSource) + ((x + 0) * 2) + stride);
                        r = (byte) (((*pixelColorComponentS & 0x7C00) >> 7) * mOffset16);
                        g = (byte) (((*pixelColorComponentS & 0x03E0) >> 2) * mOffset16);
                        b = (byte) (((*pixelColorComponentS & 0x001F) << 3) * mOffset16);
                        r = (byte) ((int) ((Limits(r, ((int) (errorR * 5)) >> 4))) & 0xF8); 
                        g = (byte) ((int) ((Limits(g, ((int) (errorG * 5)) >> 4))) & 0xF8); 
                        b = (byte) ((int) ((Limits(b, ((int) (errorB * 5)) >> 4))) & 0xF8); 
                        *pixelColorComponentS = (ushort) (r << 7 | g << 2 | b >> 3);

                        if (x + 1 < width) 
                        {
                            // Right and Down
                            pixelColorComponentS = (ushort*) ((pixelSource) + ((x + 1) * 2) + stride);
                            r = (byte) (((*pixelColorComponentS & 0x7C00) >> 7) * mOffset16);
                            g = (byte) (((*pixelColorComponentS & 0x03E0) >> 2) * mOffset16);
                            b = (byte) (((*pixelColorComponentS & 0x001F) << 3) * mOffset16);
                            r = (byte) ((int) ((Limits(r, ((int) (errorR * 1)) >> 4))) & 0xF8); 
                            g = (byte) ((int) ((Limits(g, ((int) (errorG * 1)) >> 4))) & 0xF8); 
                            b = (byte) ((int) ((Limits(b, ((int) (errorB * 1)) >> 4))) & 0xF8); 
                            *pixelColorComponentS = (ushort) (r << 7 | g << 2 | b >> 3);
                        } 
                    }
                    break;
                case 24:
                    if (x + 1 < width) 
                    { 
                        // Right
                        pixelColorComponent = ((pixelSource) + ((x + 1) * 3));
                        *pixelColorComponent = Limits(*(pixelColorComponent), (errorB * 7) >> 4); 
                        pixelColorComponent++;
                        *pixelColorComponent = Limits(*(pixelColorComponent), (errorG * 7) >> 4); 
                        pixelColorComponent++;
                        *pixelColorComponent = Limits(*(pixelColorComponent), (errorR * 7) >> 4); 
                    } 
                    if (y + 1 < height) 
                    { 
                        if (x - 1 > 0) 
                        { 
                            // Left and Down
                            pixelColorComponent = ((pixelSource) + ((x - 1) * 3) + stride);
                            *pixelColorComponent = Limits(*(pixelColorComponent), (errorB * 3) >> 4); 
                            pixelColorComponent++;
                            *pixelColorComponent = Limits(*(pixelColorComponent), (errorG * 3) >> 4); 
                            pixelColorComponent++;
                            *pixelColorComponent = Limits(*(pixelColorComponent), (errorR * 3) >> 4); 
                        } 

                        // Down
                        pixelColorComponent = ((pixelSource) + ((x + 0) * 3) + stride);
                        *pixelColorComponent = Limits(*(pixelColorComponent), (errorB * 5) >> 4); 
                        pixelColorComponent++;
                        *pixelColorComponent = Limits(*(pixelColorComponent), (errorG * 5) >> 4); 
                        pixelColorComponent++;
                        *pixelColorComponent = Limits(*(pixelColorComponent), (errorR * 5) >> 4); 

                        if (x + 1 < width) 
                        {
                            // Right and Down
                            pixelColorComponent = ((pixelSource) + ((x + 1) * 3) + stride);
                            *pixelColorComponent = Limits(*(pixelColorComponent), (errorB * 1) >> 4); 
                            pixelColorComponent++;
                            *pixelColorComponent = Limits(*(pixelColorComponent), (errorG * 1) >> 4); 
                            pixelColorComponent++;
                            *pixelColorComponent = Limits(*(pixelColorComponent), (errorR * 1) >> 4); 
                        } 
                    }
                    break;
                case 32:
                    if (x + 1 < width) 
                    { 
                        // Right
                        pixelColorComponent = ((pixelSource) + ((x + 1) * 4)) + 0;
                        *pixelColorComponent = Limits(*(pixelColorComponent), (errorB * 7) >> 4); 
                        pixelColorComponent++;
                        *pixelColorComponent = Limits(*(pixelColorComponent), (errorG * 7) >> 4); 
                        pixelColorComponent++;
                        *pixelColorComponent = Limits(*(pixelColorComponent), (errorR * 7) >> 4); 
                    } 
                    if (y + 1 < height) 
                    { 
                        if (x - 1 > 0) 
                        { 
                            // Left and Down
                            pixelColorComponent = ((pixelSource) + ((x - 1) * 4) + stride);
                            *pixelColorComponent = Limits(*(pixelColorComponent), (errorB * 3) >> 4); 
                            pixelColorComponent++;
                            *pixelColorComponent = Limits(*(pixelColorComponent), (errorG * 3) >> 4); 
                            pixelColorComponent++;
                            *pixelColorComponent = Limits(*(pixelColorComponent), (errorR * 3) >> 4); 
                        } 

                        // Down
                        pixelColorComponent = ((pixelSource) + ((x + 0) * 4) + stride);
                        *pixelColorComponent = Limits(*(pixelColorComponent), (errorB * 5) >> 4); 
                        pixelColorComponent++;
                        *pixelColorComponent = Limits(*(pixelColorComponent), (errorG * 5) >> 4); 
                        pixelColorComponent++;
                        *pixelColorComponent = Limits(*(pixelColorComponent), (errorR * 5) >> 4); 

                        if (x + 1 < width) 
                        {
                            // Right and Down
                            pixelColorComponent = ((pixelSource) + ((x + 1) * 4) + stride);
                            *pixelColorComponent = Limits(*(pixelColorComponent), (errorB * 1) >> 4); 
                            pixelColorComponent++;
                            *pixelColorComponent = Limits(*(pixelColorComponent), (errorG * 1) >> 4); 
                            pixelColorComponent++;
                            *pixelColorComponent = Limits(*(pixelColorComponent), (errorR * 1) >> 4); 
                        } 
                    }

                    break;
            }
        }

        private byte Limits(int a, int b)
        {
            return (a + b) < 0 ? (byte) 0 : (a + b) > 255 ? (byte) 255 : (byte) (a + b);
        }

        private unsafe void GetRGB(byte* firstStridePixel, byte bpp, int x, ref byte r, ref byte g, ref byte b, ref uint ARGBColor)
        {
            byte* pixelSourceBT;
            switch (bpp) 
            {
                case 16:
                    pixelSourceBT = firstStridePixel + x * 2;
                    r = (byte) ((*((ushort*) pixelSourceBT) & 0x7C00) >> 7);
                    g = (byte) ((*((ushort*) pixelSourceBT) & 0x03E0) >> 2);
                    b = (byte) ((*((ushort*) pixelSourceBT) & 0x001F) << 3);
                    ARGBColor = *((ushort*) (pixelSourceBT));
                    break;
                case 24:
                    pixelSourceBT = firstStridePixel + x * 3;
                    r = *((byte*) pixelSourceBT + 2);
                    g = *((byte*) pixelSourceBT + 1);
                    b = *((byte*) pixelSourceBT + 0);
                    ARGBColor = (uint) (r << 16 | g << 8 | b);
                    break;
                case 32:
                    pixelSourceBT = firstStridePixel + x * 4;
                    r = *((byte*) pixelSourceBT + 2);
                    g = *((byte*) pixelSourceBT + 1);
                    b = *((byte*) pixelSourceBT + 0);
                    ARGBColor = *((uint*) (pixelSourceBT));
                    break;
            }
        }
        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Creative Commons Attribution-ShareAlike 2.5 License


Written By
Software Developer Microsoft
United States United States
I started with programming about 19 years ago as a teenager, from my old Commodore moving to PC/Server environment Windows/UNIX SQLServer/Oracle doing gwBasic, QBasic, Turbo Pascal, Assembler, Turbo C, BC, Summer87, Clipper, Fox, SQL, C/C++, Pro*C, VB3/5/6, Java, and today loving C#.

Currently working as SDE on Failover Clustering team for Microsoft.

Passion for most programming languages and my kids Aidan&Nadia.

Comments and Discussions