|
| 1 | +% Fractal Image Compression using DCT |
| 2 | +clear all; |
| 3 | + |
| 4 | +% Define normalization matrices for quantization |
| 5 | +normMat = ones(16) * 10^4; |
| 6 | +normMat(1:8, 1:8) = [ |
| 7 | + 16 11 10 16 24 40 51 61 |
| 8 | + 12 12 14 19 26 58 60 55 |
| 9 | + 14 13 16 24 40 57 69 56 |
| 10 | + 14 17 22 29 51 87 80 62 |
| 11 | + 18 22 37 56 68 109 103 77 |
| 12 | + 24 35 55 64 81 104 113 92 |
| 13 | + 49 64 78 87 103 121 120 101 |
| 14 | + 72 92 95 98 112 100 103 99 |
| 15 | +]; |
| 16 | + |
| 17 | +% Initialize variables for the compression process |
| 18 | +encodingResults = zeros(1024, 10); |
| 19 | +qualityLevels = [.1 .25 .4 .5 .6 .7 .8 .95]; |
| 20 | +currentIteration = 1; |
| 21 | +errorThreshold = 7; |
| 22 | +quantizationFactor = 30; |
| 23 | + |
| 24 | +% Define image and block sizes |
| 25 | +rangeBlockSize = 16; |
| 26 | +domainBlockSize = 32; |
| 27 | + |
| 28 | +% Read and display the input image |
| 29 | +inputImage = imread('bridge.pgm'); |
| 30 | +grayscaleImage = double(inputImage); |
| 31 | +imshow(grayscaleImage / 256); |
| 32 | + |
| 33 | +% Get image dimensions |
| 34 | +imageSize = size(grayscaleImage); |
| 35 | +numBlocks = imageSize(1) / rangeBlockSize; |
| 36 | + |
| 37 | +% Divide the image into blocks and apply DCT |
| 38 | +blockIndex = 0; |
| 39 | +for row = 1:numBlocks |
| 40 | + for col = 1:numBlocks |
| 41 | + blockIndex = blockIndex + 1; |
| 42 | + currentBlock = grayscaleImage(rangeBlockSize*(row-1)+1:rangeBlockSize*row, rangeBlockSize*(col-1)+1:rangeBlockSize*col); |
| 43 | + dctBlock = dct2(currentBlock - 128); |
| 44 | + normalizedBlock = dctBlock ./ normMat; |
| 45 | + blockStorage{blockIndex} = normalizedBlock; |
| 46 | + end |
| 47 | +end |
| 48 | + |
| 49 | +% Initialize variables for the main loop |
| 50 | +totalBlocks = blockIndex; |
| 51 | +iterations = 1; |
| 52 | +currentError = errorThreshold; |
| 53 | + |
| 54 | +% Main compression loop |
| 55 | +while (iterations) |
| 56 | + matchedBlocks = 0; |
| 57 | + for i = 1:totalBlocks |
| 58 | + domainBlock = blockStorage{i}; |
| 59 | + domainBlock(1, 1) = 0; |
| 60 | + diff = 1000; |
| 61 | + |
| 62 | + % Perform distortion calculation |
| 63 | + distortion_calculation; % Custom function |
| 64 | + |
| 65 | + if (rangeBlockSize == 2) |
| 66 | + encodingResults(i, 1) = distortion; |
| 67 | + encodingResults(i, 2) = norm(domainBlock - rangeBlock); |
| 68 | + encodingResults(i, 3) = contrast; |
| 69 | + encodingResults(i, 4) = round(originalValue); |
| 70 | + iterations = 0; |
| 71 | + else |
| 72 | + if distortion < currentError |
| 73 | + matchedBlocks = matchedBlocks + 1; |
| 74 | + encodingResults(i, 3) = contrast; |
| 75 | + encodingResults(i, 4) = round(originalValue); |
| 76 | + else |
| 77 | + unmatchedBlocks(1, i-matchedBlocks) = i; |
| 78 | + encodingResults(i, 6) = 0; |
| 79 | + end |
| 80 | + end |
| 81 | + end |
| 82 | + |
| 83 | + compressionResults{iterations} = encodingResults; |
| 84 | + encodingResults = zeros(5000, 6); |
| 85 | + |
| 86 | + if (iterations ~= 0) |
| 87 | + partition_no_search; % Custom function for further partitioning |
| 88 | + end |
| 89 | +end |
| 90 | + |
| 91 | +% Calculate and display compression metrics |
| 92 | +totalTime = etime(clock, timeStart) / 60; |
| 93 | +disp(['Total compression time: ', num2str(totalTime), ' minutes']); |
| 94 | + |
| 95 | +% Calculate memory usage and compression ratio |
| 96 | +memoryUsage = (sum(encodingResults(:) ~= 0) * 12 + sum(encodingResults(:) == 0) * 13) / 8; |
| 97 | +memoryUsageKB = memoryUsage / 1024; |
| 98 | +bitsPerPixel = (memoryUsageKB / 256) * 8; |
| 99 | +compressionRatio = 256 / memoryUsageKB; |
| 100 | +disp(['Bits per pixel: ', num2str(bitsPerPixel)]); |
| 101 | +disp(['Compression ratio: ', num2str(compressionRatio)]); |
| 102 | + |
| 103 | +% Decode the compressed image |
| 104 | +fractal_dct_decompress; % Custom function for decoding |
| 105 | + |
| 106 | +% Calculate and display PSNR |
| 107 | +psnrValue = calculatePSNR(grayscaleImage, decodedImage); |
| 108 | +disp(['PSNR: ', num2str(psnrValue), ' dB']); |
| 109 | + |
| 110 | +% Custom function to calculate PSNR |
| 111 | +function psnrValue = calculatePSNR(originalImage, compressedImage) |
| 112 | + errorSum = 0; |
| 113 | + for i = 1:numel(originalImage) |
| 114 | + errorSum = errorSum + (originalImage(i) - compressedImage(i))^2; |
| 115 | + end |
| 116 | + mse = errorSum / numel(originalImage); |
| 117 | + psnrValue = 10 * log10(255^2 / mse); |
| 118 | +end |
0 commit comments