ืกื˜ื’ื ื•ื’ืจืคื™ื” ื‘-GIF

ืžื‘ื•ื

ะŸั€ะธะฒะตั‚ัั‚ะฒัƒัŽ.
ืœืคื ื™ ื–ืžืŸ ืœื ืจื‘, ื›ืฉืœืžื“ืชื™ ื‘ืื•ื ื™ื‘ืจืกื™ื˜ื”, ื”ื™ื• ืงื•ืจืกื™ื ื‘ื“ื™ืกืฆื™ืคืœื™ื ื” "ืฉื™ื˜ื•ืช ืชื•ื›ื ื” ืœืื‘ื˜ื—ืช ืžื™ื“ืข". ื”ืžืฉื™ืžื” ื—ื™ื™ื‘ื” ืื•ืชื ื• ืœื™ืฆื•ืจ ืชื•ื›ื ื™ืช ืฉืžื˜ื‘ื™ืขื” ื”ื•ื“ืขื” ื‘ืงื‘ืฆื™ GIF. ื”ื—ืœื˜ืชื™ ืœืขืฉื•ืช ืืช ื–ื” ื‘ื’'ืื•ื•ื”.

ื‘ืžืืžืจ ื–ื” ืืชืืจ ื›ืžื” ื ืงื•ื“ื•ืช ืชื™ืื•ืจื˜ื™ื•ืช, ื›ืžื• ื’ื ื›ื™ืฆื“ ื ื•ืฆืจื” ื”ืชื•ื›ื ื™ืช ื”ืงื˜ื ื” ื”ื–ื•.

ื—ืœืง ืชื™ืื•ืจื˜ื™

ืคื•ืจืžื˜ GIF

GIF (Graphics Interchange Format - ืคื•ืจืžื˜ ืœื”ื—ืœืคืช ืชืžื•ื ื•ืช) ื”ื•ื ืคื•ืจืžื˜ ืœืื—ืกื•ืŸ ืชืžื•ื ื•ืช ื’ืจืคื™ื•ืช, ื”ืžืกื•ื’ืœ ืœืื—ืกืŸ ื ืชื•ื ื™ื ื“ื—ื•ืกื™ื ืœืœื ืื™ื‘ื•ื“ ืื™ื›ื•ืช ื‘ืคื•ืจืžื˜ ืฉืœ ืขื“ 256 ืฆื‘ืขื™ื. ืคื•ืจืžื˜ ื–ื” ืคื•ืชื— ื‘ืฉื ืช 1987 (GIF87a) ืขืœ ื™ื“ื™ CompuServe ืœื”ืขื‘ืจืช ืชืžื•ื ื•ืช ืจืกื˜ืจ ื“ืจืš ืจืฉืชื•ืช. ื‘ืฉื ืช 1989 ืฉื•ื ื” ื”ืคื•ืจืžื˜ (GIF89a), ื ื•ืกืคื” ืชืžื™ื›ื” ื‘ืฉืงื™ืคื•ืช ื•ื‘ืื ื™ืžืฆื™ื”.

ืœืงื‘ืฆื™ GIF ื™ืฉ ืžื‘ื ื” ื‘ืœื•ืง. ืœื‘ืœื•ืงื™ื ื”ืืœื” ื™ืฉ ืชืžื™ื“ ืื•ืจืš ืงื‘ื•ืข (ืื• ืฉื–ื” ืชืœื•ื™ ื‘ื›ืžื” ื“ื’ืœื™ื), ื›ืš ืฉื›ืžืขื˜ ื‘ืœืชื™ ืืคืฉืจื™ ืœื˜ืขื•ืช ืื™ืคื” ื›ืœ ื‘ืœื•ืง ืžืžื•ืงื. ื”ืžื‘ื ื” ืฉืœ ืชืžื•ื ืช GIF ืœืœื ืื ื™ืžืฆื™ื” ื”ืคืฉื•ื˜ื” ื‘ื™ื•ืชืจ ื‘ืคื•ืจืžื˜ GIF89a:

ืกื˜ื’ื ื•ื’ืจืคื™ื” ื‘-GIF

ืžื›ืœ ื‘ืœื•ืงื™ื ืฉืœ ื”ืžื‘ื ื”, ื‘ืžืงืจื” ื–ื” ื ืชืขื ื™ื™ืŸ ื‘ื‘ืœื•ืง ื”ืคืœื˜ื” ื”ื’ืœื•ื‘ืœื™ ื•ื‘ืคืจืžื˜ืจื™ื ื”ืื—ืจืื™ื ืขืœ ื”ืคืœื˜ื”:

  • CT - ื ื•ื›ื—ื•ืช ืฉืœ ืคืœื˜ื” ื’ืœื•ื‘ืœื™ืช. ืื ื“ื’ืœ ื–ื” ืžื•ื’ื“ืจ, ื”ืคืœื˜ื” ื”ื’ืœื•ื‘ืœื™ืช ื—ื™ื™ื‘ืช ืœื”ืชื—ื™ืœ ืžื™ื“ ืœืื—ืจ ื ืงื•ื“ืช ื”ืื—ื™ื–ื” ื”ืœื•ื’ื™ืช ื‘ืžืกืš.
  • Size - ื’ื•ื“ืœ ืœื•ื— ื•ืžืกืคืจ ื”ืฆื‘ืขื™ื ื‘ืชืžื•ื ื”. ืขืจื›ื™ื ืขื‘ื•ืจ ืคืจืžื˜ืจ ื–ื”:

ืžื™ื“ื”
ืžืกืคืจ ืฆื‘ืขื™ื
ื’ื•ื“ืœ ืคืœื˜ื”, ื‘ืชื™ื

7
256
768

6
128
384

5
64
192

4
32
96

3
16
48

2
8
24

1
4
12

0
2
6

ืฉื™ื˜ื•ืช ื”ืฆืคื ื”

ื”ืฉื™ื˜ื•ืช ื”ื‘ืื•ืช ื™ืฉืžืฉื• ืœื”ืฆืคื ืช ื”ื•ื“ืขื•ืช ื‘ืงื•ื‘ืฆื™ ืชืžื•ื ื”:

  • ืฉื™ื˜ืช LSB (Last Significant Bit).
  • ืฉื™ื˜ืช ื”ื•ืกืคืช ืคืœื˜ื•ืช

ืฉื™ื˜ืช LSB - ืฉื™ื˜ื” ื ืคื•ืฆื” ืฉืœ ืกื˜ื’ื ื•ื’ืจืคื™ื”. ื–ื” ืžื•ืจื›ื‘ ืžื”ื—ืœืคืช ื”ื‘ื™ื˜ื™ื ื”ืžืฉืžืขื•ืชื™ื™ื ื”ืื—ืจื•ื ื™ื ื‘ืžื™ื›ืœ (ื‘ืžืงืจื” ืฉืœื ื•, ื‘ื™ื™ื˜ื™ื ืฉืœ ื”ืคืœื˜ื” ื”ื’ืœื•ื‘ืœื™ืช) ื‘ืกื™ื‘ื™ื•ืช ืฉืœ ื”ื”ื•ื“ืขื” ื”ื ืกืชืจืช.

ื”ืชื•ื›ื ื™ืช ืชืฉืชืžืฉ ื‘ืฉื ื™ ื”ื‘ื™ื˜ื™ื ื”ืื—ืจื•ื ื™ื ื‘ื‘ื™ื™ื˜ื™ื ืฉืœ ื”ืคืœื˜ื” ื”ื’ืœื•ื‘ืœื™ืช ื›ื—ืœืง ืžืฉื™ื˜ื” ื–ื•. ื”ืžืฉืžืขื•ืช ื”ื™ื ืฉืœืชืžื•ื ื” ืฉืœ 24 ืกื™ื‘ื™ื•ืช, ืฉื‘ื” ืฆื‘ืข ื”ืคืœื˜ื” ื”ื•ื ืฉืœื•ืฉื” ื‘ืชื™ื ืขื‘ื•ืจ ืื“ื•ื, ื›ื—ื•ืœ ื•ื™ืจื•ืง, ืœืื—ืจ ื”ื˜ืžืขืช ื”ื•ื“ืขื” ื‘ืชื•ื›ื”, ื›ืœ ืจื›ื™ื‘ ืฆื‘ืข ื™ืฉืชื ื” ื‘ืžืงืกื™ืžื•ื ืฉืœ 3/255 ื”ื“ืจื’ื•ืช. ืฉื™ื ื•ื™ ื›ื–ื”, ืจืืฉื™ืช, ื™ื”ื™ื” ื‘ืœืชื™ ื ืจืื” ืื• ืงืฉื” ืœื”ื‘ื—ื™ืŸ ื‘ืขื™ืŸ ื”ืื ื•ืฉื™ืช, ื•ืฉื ื™ืช, ื”ื•ื ืœื ื™ื”ื™ื” ื’ืœื•ื™ ื‘ื”ืชืงื ื™ ืคืœื˜ ืžื™ื“ืข ื‘ืื™ื›ื•ืช ื ืžื•ื›ื”.

ื›ืžื•ืช ื”ืžื™ื“ืข ืชื”ื™ื” ืชืœื•ื™ื” ื™ืฉื™ืจื•ืช ื‘ื’ื•ื“ืœ ืคืœื˜ืช ื”ืชืžื•ื ื•ืช. ืžื›ื™ื•ื•ืŸ ืฉื”ื’ื•ื“ืœ ื”ืžืจื‘ื™ ืฉืœ ื”ืคืœื˜ื” ื”ื•ื 256 ืฆื‘ืขื™ื, ื•ืื ื ื›ืชื‘ื™ื ืฉื ื™ ืกื™ื‘ื™ื•ืช ืฉืœ ื”ื•ื“ืขื” ื‘ืจื›ื™ื‘ ืฉืœ ื›ืœ ืฆื‘ืข, ืื– ืื•ืจืš ื”ื”ื•ื“ืขื” ื”ืžืงืกื™ืžืœื™ (ืขื ื”ืคืœื˜ื” ื”ืžืงืกื™ืžืœื™ืช ื‘ืชืžื•ื ื”) ื”ื•ื 192 ื‘ืชื™ื. ื‘ืจื’ืข ืฉื”ื”ื•ื“ืขื” ืžื•ื˜ืžืขืช ื‘ืชืžื•ื ื”, ื’ื•ื“ืœ ื”ืงื•ื‘ืฅ ืœื ืžืฉืชื ื”.

ืฉื™ื˜ืช ื”ืจื—ื‘ืช ื”ืฆื‘ืขื™ื, ืฉืขื•ื‘ื“ ืจืง ืขื‘ื•ืจ ืžื‘ื ื” GIF. ื–ื” ื™ื”ื™ื” ื”ื›ื™ ื™ืขื™ืœ ื‘ืชืžื•ื ื•ืช ืขื ืคืœื˜ื” ืงื˜ื ื”. ื”ืžื”ื•ืช ืฉืœื• ื”ื™ื ืฉื”ื•ื ืžื’ื“ื™ืœ ืืช ื’ื•ื“ืœ ื”ืคืœื˜ื”, ื•ื‘ื›ืš ืžืกืคืง ืžืงื•ื ื ื•ืกืฃ ืœื›ืชื™ื‘ืช ื”ื‘ืชื™ื ื”ื“ืจื•ืฉื™ื ื‘ืžืงื•ื ื‘ืชื™ื ื”ืฆื‘ืขื™ื. ืื ื ื™ืงื— ื‘ื—ืฉื‘ื•ืŸ ืฉื”ื’ื•ื“ืœ ื”ืžื™ื ื™ืžืœื™ ืฉืœ ื”ืคืœื˜ื” ื”ื•ื 2 ืฆื‘ืขื™ื (6 ื‘ืชื™ื), ืื– ื”ื’ื•ื“ืœ ื”ืžืจื‘ื™ ืฉืœ ื”ื”ื•ื“ืขื” ื”ืžื•ื˜ื‘ืขืช ื™ื›ื•ืœ ืœื”ื™ื•ืช 256 ร— 3-6 = 762 ื‘ืชื™ื. ื”ื—ื™ืกืจื•ืŸ ื”ื•ื ืื‘ื˜ื—ื” ืงืจื™ืคื˜ื•ื’ืจืคื™ืช ื ืžื•ื›ื”; ื ื™ืชืŸ ืœืงืจื•ื ืืช ื”ื”ื•ื“ืขื” ื”ืžื•ื˜ื‘ืขืช ื‘ืืžืฆืขื•ืช ื›ืœ ืขื•ืจืš ื˜ืงืกื˜ ืื ื”ื”ื•ื“ืขื” ืœื ืขื‘ืจื” ื”ืฆืคื ื” ื ื•ืกืคืช.

ื—ืœืง ืžืขืฉื™

ืขื™ืฆื•ื‘ ืชื•ื›ื ื™ืช

ื›ืœ ื”ื›ืœื™ื ื”ื“ืจื•ืฉื™ื ืœื”ื˜ืžืขืช ืืœื’ื•ืจื™ืชืžื™ ื”ืฆืคื ื” ื•ืคืขื ื•ื— ื™ื™ื›ืœืœื• ื‘ื—ื‘ื™ืœื” com.tsarik.steganography. ื—ื‘ื™ืœื” ื–ื• ื›ื•ืœืœืช ืืช ื”ืžืžืฉืง Encryptor ืขื ืฉื™ื˜ื•ืช encrypt ะธ decrypt, ืžืขืžื“ Binary, ื”ืžืกืคืง ืืช ื”ื™ื›ื•ืœืช ืœืขื‘ื•ื“ ืขื ืžืขืจื›ื™ ืกื™ื‘ื™ื•ืช, ื›ืžื• ื’ื ืžื—ืœืงื•ืช ื—ืจื™ื’ื•ืช UnableToEncryptException ะธ UnableToDecryptException, ืฉื‘ื• ื™ืฉ ืœื”ืฉืชืžืฉ ื‘ืฉื™ื˜ื•ืช ืžืžืฉืง Encryptor ื‘ืžืงืจื” ืฉืœ ืฉื’ื™ืื•ืช ืงื™ื“ื•ื“ ื•ืคืขื ื•ื— ื‘ื”ืชืืžื”.

ื—ื‘ื™ืœืช ืชื•ื›ื ื™ืช ืจืืฉื™ืช com.tsarik.programs.gifed ื™ื›ืœื•ืœ ืžื—ืœืงืช ืชื•ื›ื ื™ืช ื”ื ื™ืชื ืช ืœื”ืจืฆื” ืขื ืฉื™ื˜ื” ืกื˜ื˜ื™ืช main, ื”ืžืืคืฉืจ ืœืš ืœื”ืคืขื™ืœ ืืช ื”ืชื•ื›ื ื™ืช; ืžื—ืœืงื” ื”ืžืื—ืกื ืช ืคืจืžื˜ืจื™ื ืฉืœ ืชื•ื›ื ื™ืช; ื•ื—ื‘ื™ืœื•ืช ืขื ื›ื™ืชื•ืช ืื—ืจื•ืช.

ื™ื™ืฉื•ื ื”ืืœื’ื•ืจื™ืชืžื™ื ืขืฆืžื ื™ื•ืฆื’ ื‘ื—ื‘ื™ืœื” com.tsarik.programs.gifed.gif ืฉื™ืขื•ืจื™ื GIFEncryptorByLSBMethod ะธ GIFEncryptorByPaletteExtensionMethod. ืฉืชื™ ื”ืžื—ืœืงื•ืช ื”ืœืœื• ื™ื™ืฉืžื• ืืช ื”ืžืžืฉืง Encryptor.

ื‘ื”ืชื‘ืกืก ืขืœ ื”ืžื‘ื ื” ืฉืœ ืคื•ืจืžื˜ GIF, ืืชื” ื™ื›ื•ืœ ืœื™ืฆื•ืจ ืืœื’ื•ืจื™ืชื ื›ืœืœื™ ืœื”ื›ื ืกืช ื”ื•ื“ืขื” ืœืœื•ื— ื”ืชืžื•ื ื•ืช:

ืกื˜ื’ื ื•ื’ืจืคื™ื” ื‘-GIF

ื›ื“ื™ ืœืงื‘ื•ืข ื ื•ื›ื—ื•ืช ืฉืœ ื”ื•ื“ืขื” ื‘ืชืžื•ื ื”, ื™ืฉ ืฆื•ืจืš ืœื”ื•ืกื™ืฃ ืจืฆืฃ ืžืกื•ื™ื ืฉืœ ื‘ื™ื˜ื™ื ืœืชื—ื™ืœืช ื”ื”ื•ื“ืขื”, ืื•ืชื ื”ืžืคืขื ื— ืงื•ืจื ืชื—ื™ืœื” ื•ื‘ื•ื“ืง ืืช ื ื›ื•ื ื•ืชื. ืื ื–ื” ืœื ืชื•ืื, ืื– ื–ื” ื ื—ืฉื‘ ืฉืื™ืŸ ื”ื•ื“ืขื” ื ืกืชืจืช ื‘ืชืžื•ื ื”. ืœืื—ืจ ืžื›ืŸ ืขืœื™ืš ืœืฆื™ื™ืŸ ืืช ืื•ืจืš ื”ื”ื•ื“ืขื”. ื•ืื– ื”ื˜ืงืกื˜ ืฉืœ ื”ื”ื•ื“ืขื” ืขืฆืžื”.

ืชืจืฉื™ื ื›ื™ืชืชื™ ืฉืœ ื”ื™ื™ืฉื•ื ื›ื•ืœื•:

ืกื˜ื’ื ื•ื’ืจืคื™ื” ื‘-GIF

ื™ื™ืฉื•ื ื”ืชื•ื›ื ื™ืช

ื ื™ืชืŸ ืœื—ืœืง ืืช ื™ื™ืฉื•ื ื”ืชื•ื›ื ื™ืช ื›ื•ืœื” ืœืฉื ื™ ืžืจื›ื™ื‘ื™ื: ื™ื™ืฉื•ื ื”ืฆืคื ืช ืžืžืฉืง ื•ืฉื™ื˜ื•ืช ืคืขื ื•ื— Encryptor, ื‘ืฉื™ืขื•ืจื™ื GIFEncryptorByLSBMethod ะธ GIFEncryptorByPaletteExtensionMethod, ื•ื”ื˜ืžืขืช ืžืžืฉืง ื”ืžืฉืชืžืฉ.

ืงื—ื• ื‘ื—ืฉื‘ื•ืŸ ืืช ื”ื›ื™ืชื” GIFEncryptorByLSBMethod.

ืกื˜ื’ื ื•ื’ืจืคื™ื” ื‘-GIF

ืฉื“ื•ืช firstLSBit ะธ secondLSBit ืžื›ื™ืœื™ื ืืช ืžืกืคืจ ื”ื‘ื™ื˜ื™ื ืฉืœ ื›ืœ ื‘ื™ื™ื˜ ืฉืœ ื”ืชืžื•ื ื” ืฉืœืชื•ื›ื” ื™ืฉ ืœื”ื–ื™ืŸ ืืช ื”ื”ื•ื“ืขื” ื•ืžื”ื™ื›ืŸ ื™ืฉ ืœืงืจื•ื ืืช ื”ื”ื•ื“ืขื”. ืฉื“ื” checkSequence ืžืื—ืกืŸ ืจืฆืฃ ืกื™ื‘ื™ื•ืช ื‘ื“ื™ืงื” ื›ื“ื™ ืœื”ื‘ื˜ื™ื— ื–ื™ื”ื•ื™ ืฉืœ ื”ื”ื•ื“ืขื” ื”ืžื•ื˜ื‘ืขืช. ืฉื™ื˜ื” ืกื˜ื˜ื™ืช getEncryptingFileParameters ืžื—ื–ื™ืจื” ืืช ื”ืคืจืžื˜ืจื™ื ืฉืœ ื”ืงื•ื‘ืฅ ืฉืฆื•ื™ืŸ ื•ืืช ื”ืžืืคื™ื™ื ื™ื ืฉืœ ื”ื”ื•ื“ืขื” ื”ืคื•ื˜ื ืฆื™ืืœื™ืช.

ืืœื’ื•ืจื™ืชื ืฉื™ื˜ื” encrypt ื›ื™ืชื” GIFEncryptorByLSBMethod:

ืกื˜ื’ื ื•ื’ืจืคื™ื” ื‘-GIF

ื•ื”ืงื•ื“ ืฉืœื•:

@Override
public void encrypt(File in, File out, String text) throws UnableToEncodeException, NullPointerException, IOException {
	if (in == null) {
		throw new NullPointerException("Input file is null");
	}
	if (out == null) {
		throw new NullPointerException("Output file is null");
	}
	if (text == null) {
		throw new NullPointerException("Text is null");
	}
	
	// read bytes from input file
	byte[] bytes = new byte[(int)in.length()];
	InputStream is = new FileInputStream(in);
	is.read(bytes);
	is.close();
	
	// check format
	if (!(new String(bytes, 0, 6)).equals("GIF89a")) {
		throw new UnableToEncodeException("Input file has wrong GIF format");
	}
	
	// read palette size property from first three bits in the 10-th byte from the file
	byte[] b10 = Binary.toBitArray(bytes[10]);
	byte bsize = Binary.toByte(new byte[] {b10[0], b10[1], b10[2]});
	
	// calculate color count and possible message length
	int bOrigColorCount = (int)Math.pow(2, bsize+1);
	int possibleMessageLength = bOrigColorCount*3/4;
	int possibleTextLength = possibleMessageLength-2;// one byte for check and one byte for message length
	
	if (possibleTextLength < text.length()) {
		throw new UnableToEncodeException("Text is too big");
	}
	
	int n = 13;
	
	// write check sequence
	for (int i = 0; i < checkSequence.length/2; i++) {
		byte[] ba = Binary.toBitArray(bytes[n]);
		ba[firstLSBit] = checkSequence[2*i];
		ba[secondLSBit] = checkSequence[2*i+1];
		bytes[n] = Binary.toByte(ba);
		n++;
	}
	
	// write text length
	byte[] cl = Binary.toBitArray((byte)text.length());
	for (int i = 0; i < cl.length/2; i++) {
		byte[] ba = Binary.toBitArray(bytes[n]);
		ba[firstLSBit] = cl[2*i];
		ba[secondLSBit] = cl[2*i+1];
		bytes[n] = Binary.toByte(ba);
		n++;
	}
	
	// write message
	byte[] textBytes = text.getBytes();
	for (int i = 0; i < textBytes.length; i++) {
		byte[] c = Binary.toBitArray(textBytes[i]);
		for (int ci = 0; ci < c.length/2; ci++) {
			byte[] ba = Binary.toBitArray(bytes[n]);
			ba[firstLSBit] = c[2*ci];
			ba[secondLSBit] = c[2*ci+1];
			bytes[n] = Binary.toByte(ba);
			n++;
		}
	}
	
	// write output file
	OutputStream os = new FileOutputStream(out);
	os.write(bytes);
	os.close();
}

ืืœื’ื•ืจื™ืชื ื•ืงื•ื“ ืžืงื•ืจ ืฉืœ ื”ืฉื™ื˜ื” decrypt ื›ื™ืชื” GIFEncryptorByLSBMethod:

ืกื˜ื’ื ื•ื’ืจืคื™ื” ื‘-GIF

@Override
public String decrypt(File in) throws UnableToDecodeException, NullPointerException, IOException {
	if (in == null) {
		throw new NullPointerException("Input file is null");
	}
	
	// read bytes from input file
	byte[] bytes = new byte[(int)in.length()];
	InputStream is = new FileInputStream(in);
	is.read(bytes);
	is.close();
	
	// check format
	if (!(new String(bytes, 0, 6)).equals("GIF89a")) {
		throw new UnableToDecodeException("Input file has wrong GIF format");
	}
	
	// read palette size property from first three bits in the 10-th byte from the file
	byte[] b10 = Binary.toBitArray(bytes[10]);
	byte bsize = Binary.toByte(new byte[] {b10[0], b10[1], b10[2]});
	
	// calculate color count and possible message length
	int bOrigColorCount = (int)Math.pow(2, bsize+1);
	int possibleMessageLength = bOrigColorCount*3/4;
	int possibleTextLength = possibleMessageLength-2;	// one byte for check and one byte for message length
	
	int n = 13;
	
	// read check sequence
	byte[] csBits = new byte[checkSequence.length];
	for (int i = 0; i < 4; i++) {
		byte[] ba = Binary.toBitArray(bytes[n]);
		csBits[2*i] = ba[firstLSBit];
		csBits[2*i+1] = ba[secondLSBit];
		n++;
	}
	byte cs = Binary.toByte(csBits);
	
	if (cs != Binary.toByte(checkSequence)) {
		throw new UnableToDecodeException("There is no encrypted message in the image (Check sequence is incorrect)");
	}
	
	// read text length
	byte[] cl = new byte[8];
	for (int i = 0; i < 4; i++) {
		byte[] ba = Binary.toBitArray(bytes[n]);
		cl[2*i] = ba[firstLSBit];
		cl[2*i+1] = ba[secondLSBit];
		n++;
	}
	byte textLength = Binary.toByte(cl);
	
	if (textLength < 0) {
		throw new UnableToDecodeException("Decoded text length is less than 0");
	}
	if (possibleTextLength < textLength) {
		throw new UnableToDecodeException("There is no messages (Decoded message length (" + textLength + ") is less than Possible message length (" + possibleTextLength + "))");
	}
	
	// read text bits and make text bytes
	byte[] bt = new byte[textLength];
	for (int i = 0; i < bt.length; i++) {
		byte[] bc = new byte[8];
		for (int bci = 0; bci < bc.length/2; bci++) {
			byte[] ba = Binary.toBitArray(bytes[n]);
			bc[2*bci] = ba[firstLSBit];
			bc[2*bci+1] = ba[secondLSBit];
			n++;
		}
		bt[i] = Binary.toByte(bc);
	}
	
	return new String(bt);
}

ื™ื™ืฉื•ื ื”ืฉื™ืขื•ืจ GIFEncryptorByPaletteExtensionMethod ื™ื”ื™ื” ื“ื•ืžื”, ืจืง ืฉื™ื˜ืช ื”ืฉืžื™ืจื”/ืงืจื™ืืช ื”ืžื™ื“ืข ืฉื•ื ื”.

ื‘ื›ื™ืชื” MainFrame ืฉื™ื˜ื•ืช ืขื˜ื™ืคื” ืžืชื•ืืจื•ืช: encryptImage(Encryptor encryptor) ะธ decryptImage(Encryptor encryptor), ืขื™ื‘ื•ื“ ื”ืชื•ืฆืื•ืช ืฉืœ ืฉื™ื˜ื•ืช ืžืžืฉืง Encryptor ื•ืื™ื ื˜ืจืืงืฆื™ื” ืขื ื”ืžืฉืชืžืฉ, ื›ืœื•ืžืจ ืคืชื™ื—ืช ื“ื•-ืฉื™ื— ืœื‘ื—ื™ืจืช ืงื‘ืฆื™ื, ื”ืฆื’ืช ื”ื•ื“ืขื•ืช ืฉื’ื™ืื” ื•ื›ื•'; ื›ืžื• ื’ื ืฉื™ื˜ื•ืช ืื—ืจื•ืช: openImage(), ื”ืžืืคืฉืจ ืœืžืฉืชืžืฉ ืœื‘ื—ื•ืจ ืชืžื•ื ื”, exit(), ืืฉืจ ื™ื•ืฆื ืžื”ืืคืœื™ืงืฆื™ื”. ืฉื™ื˜ื•ืช ืืœื• ื ืงืจืื•ืช ืž Actionืคืจื™ื˜ื™ ื”ืชืคืจื™ื˜ ื”ืชื•ืืžื™ื ืฉืœ. ืžื—ืœืงื” ื–ื• ืžื™ื™ืฉืžืช ื‘ื ื•ืกืฃ ืฉื™ื˜ื•ืช ืขื–ืจ: createComponents() - ื™ืฆื™ืจืช ืจื›ื™ื‘ื™ ื˜ื•ืคืก, loadImageFile(File f) - ื˜ืขื™ื ืช ืชืžื•ื ื” ืœืจื›ื™ื‘ ืžื™ื•ื—ื“ ืžืงื•ื‘ืฅ. ื™ื™ืฉื•ื ื”ืฉื™ืขื•ืจ GIFEncryptorByPaletteExtensionMethod ื‘ื“ื•ืžื” ืœืžื™ืžื•ืฉ ื”ื›ื™ืชื” GIFEncryptorByLSBMethod, ื”ื”ื‘ื“ืœ ื”ืขื™ืงืจื™ ื”ื•ื ื‘ืื•ืคืŸ ื”ื›ืชื™ื‘ื” ื•ื”ืงืจื™ืื” ืฉืœ ื‘ืชื™ื ืฉืœ ื”ื•ื“ืขื•ืช ืžื”ืœื•ื—.

ืชืคืขื•ืœ ื”ืชื•ื›ื ื™ืช

ืฉื™ื˜ืช LBS

ื ื ื™ื— ืฉื™ืฉ ืชืžื•ื ื” ื›ื–ื•:

ืกื˜ื’ื ื•ื’ืจืคื™ื” ื‘-GIF

ื‘ืชืžื•ื ื” ื–ื•, ื”ืคืœื˜ื” ืžื•ืจื›ื‘ืช ืž-256 ืฆื‘ืขื™ื (ื›ืคื™ ืฉ-Paint ืฉื•ืžืจ). ืืจื‘ืขืช ื”ืฆื‘ืขื™ื ื”ืจืืฉื•ื ื™ื ื”ื: ืœื‘ืŸ, ืฉื—ื•ืจ, ืื“ื•ื, ื™ืจื•ืง. ืฆื‘ืขื™ื ืื—ืจื™ื ื”ื ืฉื—ื•ืจ. ืจืฆืฃ ื”ืกื™ื‘ื™ื•ืช ื”ื’ืœื•ื‘ืœื™ ืฉืœ ื”ืฆื‘ืขื™ื ื™ื”ื™ื” ื›ื“ืœืงืžืŸ:

11111111 11111111 11111111 00000000 00000000 00000000 11111111 00000000 00000000 00000000 11111111 00000000...

ืกื˜ื’ื ื•ื’ืจืคื™ื” ื‘-GIF

ืœืื—ืจ ื”ื˜ืžืขืช ื”ื”ื•ื“ืขื”, ื”ืกื™ื‘ื™ื•ืช ื”ืžืกื•ืžื ื•ืช ื‘ืงื• ืชื—ืชื•ืŸ ื™ื•ื—ืœืคื• ื‘ืกื™ื‘ื™ื•ืช ืžื”ื”ื•ื“ืขื”. ื”ืชืžื•ื ื” ื”ืžืชืงื‘ืœืช ื›ืžืขื˜ ื•ืื™ื ื” ืฉื•ื ื” ืžื”ืžืงื•ืจ.

ืžืงื•ืจื™
ืชืžื•ื ื” ืขื ื”ื•ื“ืขื” ืžื•ื˜ื‘ืขืช

ืกื˜ื’ื ื•ื’ืจืคื™ื” ื‘-GIF
ืกื˜ื’ื ื•ื’ืจืคื™ื” ื‘-GIF

ืฉื™ื˜ืช ื”ืจื—ื‘ืช ื”ืฆื‘ืขื™ื

ื›ืืฉืจ ืืชื” ืคื•ืชื— ืชืžื•ื ื” ื”ืžื›ื™ืœื” ื”ื•ื“ืขื” ื‘ืฉื™ื˜ื” ื–ื•, ืชืจืื” ืืช ื”ืชืžื•ื ื” ื”ื‘ืื”:

ืกื˜ื’ื ื•ื’ืจืคื™ื” ื‘-GIF

ื‘ืจื•ืจ ืฉืฉื™ื˜ื” ื–ื• ืœื ืชืขื‘ื•ื“ ืขื‘ื•ืจ ืคืขื™ืœื•ื™ื•ืช ืจื™ื’ื•ืœ ืžืŸ ื”ืžื ื™ื™ืŸ, ื•ืขืฉื•ื™ื” ืœื“ืจื•ืฉ ื”ืฆืคื ื” ื ื•ืกืคืช ืฉืœ ื”ื”ื•ื“ืขื”.

ื”ืฆืคื ื”/ืคืขื ื•ื— ื‘ืชืžื•ื ื•ืช ืžื•ื ืคืฉื•ืช ืขื•ื‘ื“ ื‘ื“ื™ื•ืง ื›ืžื• ื‘ืชืžื•ื ื•ืช ืกื˜ื˜ื™ื•ืช ืจื’ื™ืœื•ืช, ืืš ื”ืื ื™ืžืฆื™ื” ืื™ื ื” ืฉื‘ื•ืจื”.

ืžืงื•ืจื•ืช ื‘ืฉื™ืžื•ืฉ:

ื”ื•ืจื“ื”:

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”