Image compression/Image stretching

What maths do I need to know to grasp this concept?? I made an algorithm that decompresses an image (goes from a smaller image) to a larger image. But how do you reverse that process?

f:x->y if |x| < |y|, then stretch x (repeat x) to cover y.

f:y->x if |x| < |y|, then what happens? Some data would be lost.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
void image_stretch(char* dest, const char* src, unsigned int dest_size, unsigned int src_size)
{
	unsigned int A = src_size;
	unsigned int B = dest_size;

    unsigned int K_needed = (unsigned int) ceilf(((float)B)/((float)A));

    //if the dest_size is a multiple of src_size, then dest MOD src == 0
	unsigned int K_clamped = (!(dest_size%src_size))? B / A : (unsigned int) ::floorf(((float)B)/((float)A)); //amount of A to spread for every A on B
    //for now this assumes that B is a multiple of A, if A | B.

    /*
       | K = B/A | -> | A = B/K | -> | KA = B |
       //K is the largest amount of duplicity that A sub i is allowed to have on B.
       //if B is not a multiple of A then some rounding will occur,
       //and K amount will not be evenly distributed among B elements.
    */

    /*
        | 0 1 0 1 | -> | 0 0 1 1 0
    */

    //put it in a high speed cache cpu memory.
    register unsigned int i = 0;
    register unsigned int j = 0;

    /*
        K = B / A
        if A | B, then K { Z
        if K ~{ Z, then A ~| B

        if B >= A, then K >= 1

        B/A >= 1 -> B >= A

        if K < 1, then B < A
    */

    //goal to properly render an image if B is not a multiple of A.

    //THIS WILL NOT BE ONTO if A ~| B
    //if A ~| B, then B != AC, there exists no C (integer) that B = AC
    //for every ith byte of the src.
	for(i = 0; i < A; i++)
	{
        //distribute to the ith multiple of K, j units of the ith byte
		for(j = 0; j < K_clamped; j++)
		{
		    //for every source byte, K dest bytes
		    //linear maping of Ki+j, where j is the jth byte in the dest at the ith offset of K
            //const int cell = K*i+j;
            //accumulated error...
            const int cell = K_clamped*i+j;

			dest[cell] = src[i];
		}
	}
}


I read some where that to correct this you would take adjacent elements and average them together to form a pixel that uses all of the information. The above algorithm works if the destination size is a multiple of the source. But if not then their will be padding (empty spots) at the tail of the image. How do I improve this algorithm?
Last edited on
Consider a source bitmap of 3x3 and a destination bitmap of 2x2. Imagine them as literal arrays of colored squares, each square 1 mm on each side. Now shrink the squares in the source bitmap until they're 2/3 mm on each side, such that if you put the two bitmaps on top of each other, their size match. Note how pixel (0,0) in the destination overlaps with pixels (0,0), (1,0), (0,1), and (1,1) in the source. Also notice that the proportions of overlap for each source pixel (i.e. how much of the given pixel actually overlaps with some other pixel) are 1, 0.5, 0.5, and 0.25. If you add these, you'll see that the result is 2.25 = 9/4 = 3^3/2^2. Dividing this value by each proportion gives you the ratio of color that each source pixel will contribute to the color of the destination pixel.
So, for example, if the source bitmap was a grayscale with the following values:
255, 128, 64
51, 178, 0
255, 42, 3
then pixel (0,0) in the destination would be 255*1*(4/9) + 128*0.5*(4/9) + 51*0.5*(4/9) + 178*0.25*(4/9) = 113 + 28 + 11 + 20 = 172.
Isn't this scaling, and not compression?
Yes, they are talking about scaling.

Scaling algorithms are all about properly sampling the data. There are many methods to do that.

The key words you will want to google around are "image filtering", "resampling", and "interpolation".

If you want to jump in with something useful but not insanely difficult, google "lanczos resampling".

Wikipedia has a good article as well: http://en.wikipedia.org/wiki/Image_scaling

Remember, you are resampling the data, not sharpening it. The filters and algorithms are related, but not the same thing.

Good luck!
The Scale Image command enlarges or reduces the physical size of the image by changing the number of pixels it contains. It changes the size of the contents of the image and resizes the canvas accordingly. It operates on the entire image. If your image has layers of different sizes, making the image smaller could shrink some of them down to nothing, since a layer cannot be less than one pixel wide or high. If this happens, you will be warned before the operation is performed.

http://www.rasteredge.com/how-to/vb-net-imaging/scale-image/
http://www.rasteredge.com/how-to/vb-net-imaging/
Topic archived. No new replies allowed.