% EIFSExample This example demonstrates the use of the Encrypted Image Folding Software (EIFS)
% by reproducing the example in the paper:
%
%  [1]  Sparsity and `something else': An Approach to  Encrypted Image Folding, by James 
%       Bowley and Laura Rebollo-Neira (pdf)
%
% The image is a 256 x 256 pixel grey level intensity photo of Bertrand Russell. The EIF 
% method is applied twice, using two different approaches for the representation:
%  1) The standard DCT in 2D by disregarding the smallest coefficients.
%  2) The RDCDB dictionary - composed of Discrete Cosine (redundancy 2) plus Dirac Basis 
%     and a dedicated implementation of the Orthogonal Matching Pursuit (OMP) method for 
%     these dictionaries.
% For a much faster implementation of 2) please use the C++ implementation of OMP in 2D 
% (OMP2D).  
% For this:
%   i) compile the OMP2.cpp file and move it to EIFS/Approximation_Routines folder, all this 
%   can be done simply by running the script CompileOMP in the EIFS/Mex_Files 
%   subdirectory
%   ii) replace 'RDCTDB' below (line 58) by 'RDCTDBMex'.
% For each method, the unfolding operation is performed twice, using the correct and
% incorrect private keys. The corresponding results shown in Figures 1 and 2.

clear all;
clc;
close all;
% Setting the  dedicated inputs 
imagePath = 'Ber256.jpg';   % needed to read the image
blockWidth = 8;             % size of the blocks to split the image
publicKey = 17;             % public key to avoid plain tex attack
rotate = 1;                 % use rotation for the encryption operation
%% Starts the Example by method 1) (DCT Approach for the image approximation)
method1 = 'DCT';    % Method 1) DCT 
PSNR = 40.17;              % Approximate desired PSNR for the approximation
privateKey1 = 987654321;   % Folding using this private key
tic;
[mFoldedImage, cIndex, mImage, maxIntensity ] = ...
    FoldImage(imagePath, method1, PSNR, blockWidth,publicKey,privateKey1,rotate);
%
saveImagePath1 = ['folded_', method1 '.jpg']; %Path to save the folded image
SaveImage(mFoldedImage,saveImagePath1,maxIntensity);
% The folding was performed - The output  was saved as jpg file (folded_Ber256_DCT.jpg)
% Recovering of the folded image starts - Requested inputs are
% cIndex (indices of the sparse representations) and Private key 
privateKey2 = 123456789; %Private key 
mLoadedImageDCT = double(imread(saveImagePath1)); % Folded image read from a jpg file. 
%
mRecoveredImageDCT1 = ExpandImage(mLoadedImageDCT, cIndex, method1, blockWidth, publicKey, privateKey2, rotate);
timeDCT = toc;
PSNR1 = CalcPSNR(mImage,mRecoveredImageDCT1);
fprintf('PSNR in recovery with INCORRECT key: %.2f\n',PSNR1);
% The recovery was already attempted with an INCORRECT key (mRecoveredImageDCT1)
% Next the recovery  with the CORRECT Key 
privateKey1 = 987654321; 
mRecoveredImageDCT2 = ExpandImage(mLoadedImageDCT, cIndex, method1, blockWidth, publicKey, privateKey1, rotate);
PSNR2 = CalcPSNR(mImage,mRecoveredImageDCT2);
fprintf('PSNR in recovery with  the CORRECT key: %.2f\n',PSNR2);
%% Start the Example by method 2) (RDCDB Approach for the image approximation)
method2 = 'RDCTDB';  % just change to RDCDBMex - For this OMP2Dmex has to be compiled (see manual)
%
saveImagePath2 = ['folded_', method2 '.jpg'];
PSNR = 40.57;
privateKey1 = 987654321; %Folding  using this key
tic
[ mFoldedImage, cIndex, mImage, maxIntensity ] = ...
    FoldImage(imagePath, method2, PSNR, blockWidth,publicKey,privateKey1,rotate);
SaveImage(mFoldedImage,saveImagePath2,maxIntensity);
% The folding was performed  - The output  was saved as jpg file (folded_Ber256_RDCTDB.jpg)
%
privateKey2 = 123456789;
mLoadedImageRDCTDB = double(imread(saveImagePath2));
mRecoveredImageRDCTDB1 = ExpandImage(mLoadedImageRDCTDB, cIndex, method2, blockWidth, publicKey, privateKey2, rotate);
PSNR1 = CalcPSNR(mImage,mRecoveredImageRDCTDB1);
fprintf('PSNR in recovery with an INCORRECT key: %.2f\n',PSNR1);
%The recovery was  already attempted with an INCORRECT  key (mRecoveredImageRDCTDB1)
timeRDCTDB = toc;
% Next the recover the images with the CORRECT Key
privateKey1 = 987654321;
mRecoveredImageRDCTDB2 = ExpandImage(mLoadedImageRDCTDB, cIndex, method2, blockWidth, publicKey, privateKey1, rotate);
PSNR2 = CalcPSNR(mImage,mRecoveredImageRDCTDB2);
fprintf('PSNR in recovery with the CORRECT key: %.2f\n',PSNR2);
%% Display processing time;
PrintWithStars('Processing Time');
fprintf('Time for %s: %.2f seconds\n',method1,timeDCT);
fprintf('Time for %s: %.2f seconds\n',method2,timeRDCTDB);
%% Display Images
% Display of Figure 1 (DCT method)  containing: Image  and folded Image (top pictures)
%                         unfolded images with right and wrong keys (bottom pictures)
MakeFigures(mImage,mLoadedImageDCT,mRecoveredImageDCT1,mRecoveredImageDCT2,method1,maxIntensity);
%
% Display of Figure 2 (RDCDB method) containing: Image  and folded Image (top pictures)
%                         unfolded images with right and wrong keys (bottom pictures)
MakeFigures(mImage,mLoadedImageRDCTDB,mRecoveredImageRDCTDB1,mRecoveredImageRDCTDB2,method2,maxIntensity);
