%% Transform Compression JPEG
% JPEG Baseline Encoder
% Jorge Calderon <calderonjorge9@gmail.com>
% University Of Antioquia
% Created: November 2012
% Modified: January 2013
% Copyright 2012
% All rights reserved
%% Clean Workplace
clear all;
close all;
clc;
%% Initialize Variables
check = 0;
stream=[];
DCTQ=[...
16 11 10 16 24 40 51 61;...
12 12 14 19 26 58 60 55;...
14 13 16 24 40 57 69 56;...
14 17 22 29 51 87 80 62;...
18 22 37 56 68 109 103 77;...
24 36 55 64 81 194 113 92;...
49 64 78 87 103 121 120 101;...
72 92 95 98 112 100 103 99];
z=[...
9 2 3 10 17 25 18 11 4 5 12 19 26 ...
33 41 34 27 20 13 6 7 14 21 28 35 ...
42 49 57 50 43 36 29 22 15 8 16 23 ...
30 37 44 51 58 59 52 45 38 31 24 32 ...
39 46 53 60 61 54 47 40 48 55 62 63 56 64];
%% Read Image
while check<1
[img_in pathname]=uigetfile({'*.bmp;*.tif','Image(*.bmp,*.tif)'},'Select Uncompressed Image','Multiselect','off');
if img_in>0
cd(pathname)
image = double(imread(img_in));
[row, col, dim] = size(image);
if col<row
disp('Error: The image must be horizontal');
disp('Press any key to continue...');
pause;
else
if (row<720 && col<1280)
check=1;
else
disp('Error: The image size is too large');
disp('Press any key to continue...');
pause;
end
end
else
if img_in==0
return;
end
end
end
%% Check Size
if mod(row,2)~=0
row = row-1;
end
if mod(col,2)~=0
col = col-1;
end
image = imresize(image, [row col]);
%% Convert Image To YCBCR
img = rgb2ycbcr(image);
%% Adjust Aspect Ratio
if mod(row,72)~=0
row_aspect = row+(72-mod(row,72));
else
row_aspect = row;
end
col_aspect = (row_aspect/9)*16;
image_aspect = zeros(row_aspect, col_aspect, dim);
zig_zag_ac = zeros(row_aspect*col_aspect/64, 63);
zig_zag_dc = zeros(row_aspect*col_aspect/64, 1);
for i=1:col
for j=1:row
for k=1:dim
image_aspect(j+abs(row_aspect-row)/2,i+abs(col_aspect-col)/2,k)=img(j,i,k);
end
end
end
% figure(1)
% imshow(uint8(image_aspect));
%% Digitization Scheme 420
comp_blue = image_aspect(:,:,2);
comp_red = image_aspect(:,:,3);
luminance = double(image_aspect(:,:,1))-128;
imgcb_420 = double(comp_blue(1:2:size(comp_blue,1),1:2:size(comp_blue,2)))-128;
imgcr_420 = double(comp_red(1:2:size(comp_red,1),1:2:size(comp_red,2)))-128;
%% Segmenting Image Blocks Of 8x8
k=0;
for i=1:8:row_aspect
for j=1:8:col_aspect
f=luminance(i:i+7,j:j+7);
T=dct2(f);
TQ=round(T./DCTQ);
k=k+1;
zig_zag_dc(k,1) = TQ(1,1);
zig_zag_ac(k,1:63) = TQ(z);
end
end
%% Huffman Compression
dpcm(1,1)=zig_zag_dc(1,1);
stream=cat(2,stream,huffman_dc(dpcm(1,1)),huffman_ac(zig_zag_ac(1,1:63)));
for m=2:k
dpcm(m,1)=zig_zag_dc(m,1)-zig_zag_dc(m-1,1);
stream=cat(2,stream,huffman_dc(dpcm(m,1)),huffman_ac(zig_zag_ac(m,1:63)));
end
%% Byte Stuffing
p=0;
G=size(stream,2);
for i=1:8:size(stream,2)
bit_val(1,1:8)=stream(1,i:i+7);
if strcmp(bit_val(1,1:8),'11111111')==1
tempbitstream = stream(1,i+8:G+p);
stream(1,i+8:i+15)='00000000';
p=p+8;
temp2_bitstream=stream(1,1:i+15);
stream(1,1:G+p)=cat(2,temp2_bitstream,tempbitstream);
end
end
%% Convert String To Decimal
numbytes=floor(length(stream)/8);
diff_stream=length(stream)-numbytes*8;
if diff_stream==0
matrix_code_decimal= zeros(numbytes+2,8);
else
matrix_code_decimal= zeros(numbytes+3,8);
end
s=0;
for count2=1:8:numbytes*8
s=s+1;
matrix_code_decimal(s,1)=bin2dec(stream(1,count2:count2+7));
end
if diff_stream~=0
s=s+1;
matrix_code_decimal(s,1)=bin2dec(stream(1,numbytes*8+1:length(stream)));
end
%% Final Marker
matrix_code_decimal(s+1,1)=255;
matrix_code_decimal(s+2,1)=217;
%% Header JFIF
signal=[255 216 255 224 000 016 074 070 073 070 000 001 002 000 000 096 000 096 000 000 ...
255 219 000 067 000 016 011 012 014 012 010 016 014 013 014 018 017 016 019 024 ...
040 026 024 022 022 024 049 036 037 029 040 058 051 061 060 057 051 056 055 064 ...
072 092 078 064 068 087 069 055 056 080 109 081 087 095 098 103 194 103 062 077 ...
113 121 112 100 120 092 101 103 099 255 219 000 067 001 017 018 018 024 021 024 ...
047 026 026 047 099 066 056 066 099 099 099 099 099 099 099 099 099 099 099 099 ...
099 099 099 099 099 099 099 099 099 099 099 099 099 099 099 099 099 099 099 099 ...
099 099 099 099 099 099 099 099 099 099 099 099 099 099 099 099 099 099 255 192 ...
000 011 008 000 000 000 000 001 001 034 000 255 196 000 031 000 000 001 005 001 ...
001 001 001 001 001 000 000 000 000 000 000 000 000 001 002 003 004 005 006 007 ...
008 009 010 011 255 196 000 181 016 000 002 001 003 003 002 004 003 005 005 004 ...
004 000 000 001 125 001 002 003 000 004 017 005 018 033 049 065 006 019 081 097 ...
007 034 113 020 050 129 145 161 008 035 066 177 193 021 082 209 240 036 051 098 ...
114 130 009 010 022 023 024 025 026 037 038 039 040 041 042 052 053 054 055 056 ...
057 058 067 068 069 070 071 072 073 074 083 084 085 086 087 088 089 090 099 100 ...
101 102 103 104 105 106 115 116 117 118 119 120 121 122 131 132 133 134 135 136 ...
137 138 146 147 148 149 150 151 152 153 154 162 163 164 165 166 167 168 169 170 ...
178 179 180 181 182 183 184 185 186 194 195 196 197 198 199 200 201 202 210 211 ...
212 213 214 215 216 217 218 225 226 227 228 229 230 231 232 233 234 241 242 243 ...
244 245 246 247 248 249 250 255 218 000 008 001 001 000 000 063 000];
% Start of Image (SOI) marker:FFD8=255,216
% JFIF marker:FFE0=255,224
% Length=000,016
% Identifier:4A46494600=074,070,073,070,000
% Version=001,002
% Units=000
% Xdensity=000,096
% Ydensity=000,096
% Xthumbnail=000
% Ythumbnail=000
% (RGB)n, n=Xthumbnail*Ythumbnail required 3*n bytes=null
% Define Quantization table marker (luma):FFDB=255,219
% Length:two bytes that indicate the number of bytes, including the two length bytes, that this header contains=000,067
% Precision=000 (baseline)
% Quantization values=016,011,012,014,012,010,016,...,101,103,099 (zigzag)
% Define Quantization table marker (Chroma):FFDB=255,219
% Length:two bytes that indicate the number of bytes, including the two length bytes, that this header contains=000,067
% Precision=000 (baseline)
% Quantization values=017,018,018,024,021,024,047,...,099,099,099 (zigzag)
% Start of frame marker:FFC0=255,192
% Length:two bytes that indicate the number of bytes, including the two length bytes, that this header contains=000,011
% Sample precision=008
% X=000,000 (This will be defined later)
% Y=000,000 (This will be defined later)
% Number of components in the image=001
% * 3 for color baseline
% * 1 for grayscale baseline
% Component ID=001
% H and V sampling factors=034
% Quantization table number=000
% Define Huffman table marker (DC):FFC4=255,196
% Length:two bytes that indicate the number of bytes, including the two length bytes, that this header contains=000,031
% Index=000 (Huffman DC)
% Bits=The next 16 bytes from an array of unsigned 1-byte integers whose elements give the number of Huffman codes for each possible code length (1-16).
% Huffman values=000,001,002,...,010,011
% Define Huffman table marker (AC):FFC4=255,196
% Length:two bytes that indicate the number of bytes, including the two length bytes, that this header contains=000,181
% Index=016 (Huffman AC)
% Bits=The next 16 bytes from an array of unsigned 1-byte integers whose elements give the number of Huffman codes for each possible code length (1-16).
% Huffman values=001,002,003,...,249,250
% Start of Scan marker:FFDA=255,218
% Length:two bytes that indicate the number of bytes, including the two length bytes, that this header contains=000,008
% Number of components=001
% Component ID=001
% DC and AC table numbers=000
% Ss=000
% Se=063
% Ah and Al=000
%% Define Size Image
Y = dec2hex(row_aspect,4);
X = dec2hex(col_aspect,4);
signal(1,164) = hex2dec(Y(1,1:2));
signal(1,165) = hex2dec(Y(1,3:4));
signal(1,166) = hex2dec(X(1,1:2));
signal(1,167) = hex2dec(X(1,3:4));
%% Concatenate Coding + Header
JP_STREAM(1,1:size(signal,2))=signal(1,1:size(signal,2));
for j=1:1:size(matrix_code_decimal,1)
JP_STREAM(1,size(signal,2)+j)=matrix_code_decimal(j,1);
end
%% JPG Data Store
JP_STREAM=JP_STREAM';
img_name = regexp(img_in,'\.','split');
img_name = img_name{1};
fid = fopen([img_name '.jpg'], 'wb');
if fid < 0
error('Failed to open data file for write');
end
fwrite(fid,JP_STREAM,'uint8');
fclose(fid);