2
votes

I'm working on LSB-DCT based Image steganography in which i have to apply LSB to DCT coefficients of the image for data embedding to JPEG.i'm new to all this.so searched and read some research papers they all lack a lot of information regarding the process after DCT.i also read many questions and answers on stackoverflow too and got more confused.

here are the questions:

1-reasearch paper and in question on the web they all are using 8x8 block size from image for DCT..what i should do if the resolution of image does not completely divides into 8x8 blocks like 724 x 520.
520 / 8 = 65 but 724 / 8 = 90.5

2-if i have a lot of blocks and some information to hide which we suppose can fit into 5 blocks..do i still need to take dct of the remaining blocks and and idct.

3-do i need to apply quantization after dct and then apply lsb or i can apply lsb directly??

4-research papers are not mentioning anything about not to touch quantized dct coefficients with value 0 and 1 and the first value..now should i use them or not?? and why not?? i get it about the 0 because it's was high frequency components and is removed in JPEG for compression..and i'm not doing any compression..so can i use it and still produce the same JPEG file???

5-in quantization we divide the DCT Coefficients with quantization matrix and round off the values.in reverse,i have to multiply quantization matrix with DCT Coefficients just..no undo for round off???

For the Comment on DCT and then IDCT:

From different Research Papers: enter image description here

1
Can you please name the papers which include your extracts? For the first one I found A Mondal et. al (2015) - A Novel Approach of Image Based Steganography Using Pseudorandom Sequence Generator Function and DCT Coefficients and for the second D Singla et. al (2012) - Data Security Using LSB & DCT Steganography In Images. I can expand in my answer about them, but they are not about saving the image to jpeg.Reti43
so what they are about???Sameer Azeem

1 Answers

5
votes

JPEG steganography

If you want to save your image to jpeg, you have to follow the jpeg encoding process. Unfortunately, papers most I've read say don't do it justice. The complete process is the following (wiki summary of a 182-page specifications book):

  1. RGB to YCbCr conversion (optional),
  2. subsampling of the chroma channels (optional),
  3. 8x8 block splitting,
  4. pixel value recentering,
  5. DCT,
  6. quantisation based on compression ratio/quality,
  7. order the coefficients in a zigzag pattern, and
  8. entropy encoding; most frequently involving Huffman coding and run-length encoding (RLE).

There are actually a lot more details involved, such as headers, section markers, specifics of how to store the DC and AC coefficients, etc. Then, there are aspects that the standard has only loosely defined and their implementation can vary between codecs, e.g., subsampling algorithm, quantisation tables and entropy encoding. That said, most pieces of software abide by the general JFIF standard and can be read by various software. If you want your jpeg file to do the same, be prepared to write hundreds (to about a thousand) lines of code just for an encoder. You're better off borrowing an encoder that has already been published on the internet than writing your own. You can start by looking into libjpeg which is written in C and forms the basis of many other jpeg codecs, its C# implementation or even a Java version inspired by it.

In some pseudocode, the encoding/decoding process can be described as follows.

function saveToJpeg(pixels, fileout) {
    // pixels is a 2D or 3D array containing your raw pixel values
    // blocks is a list of 2D arrays of size 8x8 each, containing pixel values
    blocks = splitBlocks(pixels);
    // a list similar to blocks, but for the DCT coefficients
    coeffs = dct(blocks);
    saveCoefficients(coeffs, fileout);
}

function loadJpeg(filein) {
    coeffs = readCoefficients(filein);
    blocks = idct(coeffs);
    pixels = combineBlocks(blocks);
    return pixels;
}

For steganography, you'd modify it as follows.

function embedSecretToJpeg(pixels, secret, fileout) {
    blocks = splitBlocks(pixels);
    coeffs = dct(blocks);
    modified_coeffs = embedSecret(coeffs, secret);
    saveCoefficients(modified_coeffs, fileout);
}

function extractSecretFromJpeg(filein) {
    coeffs = readCoefficients(filein);
    secret = extractSecret(coeffs);
    return secret;
}

If your cover image is already in jpeg, there is no need to load it with a decoder to pixels and then pass it to an encoder to embed your message. You can do this instead.

function embedSecretToJpeg(pixels, secret, filein, fileout) {
    coeffs = readCoefficients(filein);
    modified_coeffs = embedSecret(coeffs, secret);
    saveCoefficients(modified_coeffs, fileout);
}

As far as your questions are concerned, 1, 2, 3 and 5 should be taken care of by the encoder/decoder unless you're writing one yourself.

Question 1: Generally, you want to pad the image with the necessary number of rows/columns so that both the width and height are divisible by 8. Internally, the encoder will keep track of the padded rows/columns, so that the decoder will discard them after reconstruction. The choice of pixel value for these dummy rows/columns is up to you, but you're advised against using a constant value because it will result to ringing artifacts which has to do with the fact that the Fourier transform of a square wave being the sinc function.

Question 2: While you'll modify only a few blocks, the encoding process requires you to transform them all so they can be stored to a file.

Question 3: You have to quantise the float DCT coefficients as that's what's stored losslessly to a file. You can modify them to your heart's content after the quantisation step.

Question 4: Nobody prevents you from modifying any coefficient, but you have to remember each coefficient affects all 64 pixels in a block. The DC coefficient and the low frequency AC ones introduce the biggest distortions, so you might want to stay away from them. More specifically, because of the way the DC coefficients are stored, modifying one would propage the distortion to all following blocks.

Since most high frequency coefficients are 0, they are efficiently compressed with RLE. Modifying a 0 coefficient may flip it to a 1 (if you're doing basic LSB substitution), which disrupts this efficient compression.

Lastly, some algorithms store their secret in any non-zero coefficients and will skip any 0s. However, if you attempted to modify a 1, it might flip to a 0 and in the extraction process you'd blindly skip reading it. Therefore, such algorithms don't go near any coefficients with the value of 1 or 0.

Question 5: In decoding you just multiply the coefficient with the respective quantisation table value. For example, the DC coefficient is 309.443 and quantisation gives you round(309.443 / 16) = 19. The rounding off bit is the lossy part here, which doesn't allow you to reconstruct 309.433. So the reverse is simply 19 * 16 = 304.

Other uses of DCT in steganography

Frequency transforms, such as DCT and DWT can be used in steganography to embed the secret in the frequency domain but not necessarily store the stego image to jpeg. This process is pixels -> DCT -> coefficients -> modify coefficients -> IDCT -> pixels, which is what you send to the receiver. As such, the choice of format matters here. If you decide to save your pixels to jpeg, your secret in the DCT coefficients may be disturbed by another layer of quantisation from the jpeg encoding.