zoukankan      html  css  js  c++  java
  • Ascii85 Algorithm

    Ascii85 use five ASCII characters to represent four bytes of binary data (encoded size 25% larger), it is more efficient than Base64, which use four characters to represent three bytes of data (33% increase). This encode method is suitable for posting small blocks of binary data to BBS or forum as plain text. It is also used in Portable Document Format. I implemented this algoritm in C# when doing my PDF processor project. You can find more description about ASCII85 in Wikipedia.

    The code
        /// <summary>
        
    /// Adobe ASCII85 for encoding binary data in ASCII base-85
        
    /// </summary>
        public class ASCII85
        {
            
    /// <summary>
            
    /// Maximum line length for encoded ASCII85 string; 
            
    /// set to zero for one unbroken line.
            
    /// </summary>
            public static int LineLength = 75;

            
    static uint[] pow85 = { 85 * 85 * 85 * 8585 * 85 * 8585 * 85851 };

            
    /// <summary>
            
    /// Encodes binary data into a plaintext ASCII85 format string
            
    /// </summary>
            
    /// <param name="data">binary data to encode</param>
            
    /// <returns>ASCII85 encoded string</returns>
            public static string Encode(byte[] data)
            {
                MemoryStream input 
    = new MemoryStream(data);
                MemoryStream output 
    = new MemoryStream();
                Encode(input, output);
                output.Position 
    = 0;
                StreamReader reader 
    = new StreamReader(output, Encoding.ASCII);
                
    return reader.ReadToEnd();
            }

            
    /// <summary>
            
    /// Decodes an ASCII85 encoded string into the original binary data
            
    /// </summary>
            
    /// <param name="code">ASCII85 encoded string</param>
            
    /// <returns>byte array of decoded binary data</returns>
            public static byte[] Decode(string code)
            {
                MemoryStream input 
    = new MemoryStream(Encoding.ASCII.GetBytes(code));
                MemoryStream output 
    = new MemoryStream();
                Decode(input, output);
                
    return output.ToArray();
            }

            
    /// <summary>
            
    /// Encodes the specified input.
            
    /// </summary>
            
    /// <param name="input">The input.</param>
            
    /// <param name="output">The output.</param>
            public static void Encode(Stream input, Stream output)
            {
                StreamWriter writer 
    = new StreamWriter(output, Encoding.ASCII);
                
    uint word = 0;
                
    int count = 0;
                
    int linepos = 0;
                
    int code = input.ReadByte();
                
    while (code != -1)
                {
                    word 
    |= (uint)(code << (24 - (count * 8)));
                    count
    ++;
                    
    if (count == 4)
                    {
                        
    if (word == 0)
                        {
                            writer.Write(
    'z');
                            linepos
    ++;
                        }
                        
    else
                        {
                            writer.Write(Encode(word));
                            linepos 
    += 5;
                        }
                        word 
    = 0;
                        count 
    = 0;
                    }
                    
    if (linepos >= LineLength)
                    {
                        writer.WriteLine();
                        linepos 
    = 0;
                    }
                    code 
    = input.ReadByte();
                }
                
    if (count > 0)
                {
                    writer.Write(Encode(word), 
    0, count + 1);
                }
                writer.Write(
    "~>");
                writer.Flush();
            }

            
    private static char[] Encode(uint word)
            {
                
    char[] group = new char[5];
                
    for (int i = group.Length - 1; i >= 0; i--)
                {
                    group[i] 
    = (char)(word % 85 + 33);
                    word 
    /= 85;
                }
                
    return group;
            }

            
    /// <summary>
            
    /// Decodes the specified input.
            
    /// </summary>
            
    /// <param name="input">The input.</param>
            
    /// <param name="output">The output.</param>
            public static void Decode(Stream input, Stream output)
            {
                BinaryWriter writer 
    = new BinaryWriter(output);
                
    uint word = 0;
                
    int count = 0;
                
    int code = input.ReadByte();
                
    while (code != -1)
                {
                    
    if (code == 122// 'z'
                    {
                        
    if (count == 0)
                        {
                            writer.Write((
    uint)0);
                        }
                        
    else
                        {
                            
    throw new Exception("A z character occurs in the middle of a group.");
                        }
                    }
                    
    else if (code >= 33 && code <= 117)
                    {
                        word 
    += (uint)((code - 33* pow85[count]);
                        count
    ++;
                        
    if (count == 5)
                        {
                            writer.Write(Word2Bytes(word));
                            word 
    = 0;
                            count 
    = 0;
                        }
                    }
                    
    else
                    {
                        
    switch (code)
                        {
                            
    case 0:
                            
    case 9:  // HT
                            case 10// LF
                            case 11// VT
                            case 12// FF
                            case 13// CR
                            case 32// SP
                                break;
                            
    case 126// ~>
                                goto end;
                            
    default:
                                
    throw new Exception("Invalid character in ASCII85Decode:" + code);
                        }
                    }
                    code 
    = input.ReadByte();
                }
            end:
                
    if (count > 0)
                {
                    count
    --;
                    word 
    += pow85[count]; // add maximum remained value
                    writer.Write(Word2Bytes(word), 0, count);
                }
                writer.Flush();
            }

            
    /// <summary>
            
    /// split uint32 into bytes by big-endian order
            
    /// </summary>
            
    /// <param name="word"></param>
            
    /// <returns></returns>
            static byte[] Word2Bytes(uint word)
            {
                
    byte[] bytes = new byte[4];
                bytes[
    0= (byte)((word & 0xFF000000>> 24);
                bytes[
    1= (byte)((word & 0x00FF0000>> 16);
                bytes[
    2= (byte)((word & 0x0000FF00>> 8);
                bytes[
    3= (byte)(word & 0x000000FF);
                
    return bytes;
            }
        }
  • 相关阅读:
    leetcode 48. Rotate Image
    leetcode 203. Remove Linked List Elements 、83. Remove Duplicates from Sorted List 、82. Remove Duplicates from Sorted List II(剑指offer57 删除链表中重复的结点) 、26/80. Remove Duplicates from Sorted ArrayI、II
    leetcode 263. Ugly Number 、264. Ugly Number II 、313. Super Ugly Number 、204. Count Primes
    leetcode 58. Length of Last Word
    安卓操作的一些问题解决
    leetcode 378. Kth Smallest Element in a Sorted Matrix
    android studio Gradle Build速度加快方法
    禁用gridview,listview回弹或下拉悬停
    Android Studio找不到FragmentActivity类
    安卓获取ListView、GridView等滚动的距离(高度)
  • 原文地址:https://www.cnblogs.com/rufi/p/1636968.html
Copyright © 2011-2022 走看看