willy
willy

Reputation: 473

ascii85 decoder algorithm for adobe fails in some cases

I am trying to develop a Ascii85 decoder in c++, in order to parse a bitmap file from an adobe illustrator file (*ai).

I have found an algorithm in java here and I have tried to rewrite it in c++.

The problem is that I have some cases that my encoded text is not being decoded correctly. For example if character "a" is the 7th and final character in my string (before the encoding) it is decoded as "`", which is the previous character in the ascii table. It is weird because I have tried to make the calculations of the algorithm manually, and I get "`" as a result. I am wondering if there is a bug in the algorithm or if it is not the correct algorithm for adobe ascii85 decoding.

Here is my code:

#include <QCoreApplication>
#include <stdio.h>
#include <string.h>
#include <QDebug>

// returns 1 when there are no more bytes to decode
// 0 otherwise
int decodeBlock(char *input, unsigned char *output, unsigned int inputSize) {
    qDebug() << input << output << inputSize;
    if (inputSize > 0) {
        unsigned int bytesToDecode = (inputSize < 5)? inputSize : 5;

        unsigned int x[5] = { 0 };
        unsigned int i;
        for (i = 0; i < bytesToDecode; i++) {
            x[i] = input[i] - 33;
            qDebug() << x[i] << ", i: " << i;
        }

        if (i > 0)
            i--;

        unsigned int value =
                x[0] * 85 * 85 * 85 * 85 +
                x[1] * 85 * 85 * 85 +
                x[2] * 85 * 85 +
                x[3] * 85 +
                x[4];

        for (unsigned int j = 0; j < i; j++) {
            int shift = 8 * (3 - j); // 8 * 3, 8 * 2, 8 * 1, 8 * 0
            unsigned char byte = (unsigned char)((value >> shift) & 0xff);
            printf("byte: %c, %d\n", byte, byte);
            *output = byte;
            output++;
        }
    }

    return inputSize <= 5;
}


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    char x__input[] = "<~FE1f+@;K?~>";

    unsigned char x__output[128] = { 0 };

    char *input = x__input + 2;
    unsigned int inputSize = (unsigned int)strlen(input);
    inputSize -= 2;

    unsigned char *output = x__output;

    printf("decoding %s\n", input);
    for (unsigned int i = 0; i < inputSize; i += 5, input += 5, output += 4)
        if(decodeBlock(input, output, inputSize - i))
            break;

    printf("Output is: %s\n", x__output);

    return a.exec();
}

Upvotes: 1

Views: 1280

Answers (1)

LoPiTaL
LoPiTaL

Reputation: 2605

What happens when inputSize is not multiple of 5??

    unsigned int bytesToDecode = (inputSize < 5)? inputSize : 5;

you ASSUME that bytesToDecode is 5, while there will be some bytes with unknown values

So, when your character is the last at position 7, the above condition is true.

If the input is not a multiple of 5, then it MUST be padded with the value "u". For more details about the encoding / decoding process, please check the Wikipedia page, where it is pretty well explained:

http://en.wikipedia.org/wiki/Ascii85#Example_for_Ascii85

Upvotes: 2

Related Questions