I did my own undergrad project on JPEG steganography, and I was surprised that section 2.6 accurately represents popular algorithms being implemented today. At the time it seemed to me that you got significantly better results than the naive algorithm when measuring visible differences and statistical anomalies in two ways...
1) Consider the unquantised DCT coefficients. If the unquantised coefficient is 12, and the quantisation factor is 5, then the quantised value is round(12/5) = round(2.4) = 2. If you need to flip the LSB, then the F5 algorithm would change this to 1. My algorithm would have changed this to 3 instead as this was much closer to the unrounded 2.4.
2) Encode one bit into multiple quantised co-efficients. For example: If you only need to hide one bit in a block, xor together the LSB of all 64 quantised co-efficients and use that; if you need to flip it, then carefully choose the single co-efficient which produces the best result for your visual/statistical models. (I might have excluded the DC co-efficient, don't remember.) If you need to hide two bits, use half of the co-efficients for one bit, and half for the other, and so on. Conversely, this method could also be extended to so that one bit is encoded into multiple blocks.
Rather than a keyed shuffle, I simply required the secret message to be strongly encrypted. This appears to have the added advantage of a message with predictable statistical properties.
Note also that robustness was not one of my criteria at the time.
Hope this is of some value (or at least interest). And my apologies if I have some of the terminology wrong - this was nearly twenty years ago and I don't have the work in front of me right now!
Just for clarity's sake, I use F5 to flip bits. Your suggestion in 1) makes sense to me, although I've not read of somebody trying this - if you have any more data on it I'd love to see it.
2) This general idea is a good one and the way it is used in steganography is Wet Paper Codes. These effectively provide options for how to encode short messages so you can select that which best matches the coefficients which already exist. A simple example:
Encode 00 as either 0000, 0001, 0010 or 0011
Encode 01 as either 0100, 0101, 0110 or 0111
And so on
Hence when we wish to send a 2-bit message we often only need to change a single bit in the coefficients to get to a correct code word.
Hence Wet Paper Codes are able to achieve a high ratio of bits transferred to bits flipped.
I'm sure a keyed shuffle is the right way to go, certainly also encrypting is helpful but I see no downside of more evenly spreading changes across an image using a shuffle.
1) Consider the unquantised DCT coefficients. If the unquantised coefficient is 12, and the quantisation factor is 5, then the quantised value is round(12/5) = round(2.4) = 2. If you need to flip the LSB, then the F5 algorithm would change this to 1. My algorithm would have changed this to 3 instead as this was much closer to the unrounded 2.4.
2) Encode one bit into multiple quantised co-efficients. For example: If you only need to hide one bit in a block, xor together the LSB of all 64 quantised co-efficients and use that; if you need to flip it, then carefully choose the single co-efficient which produces the best result for your visual/statistical models. (I might have excluded the DC co-efficient, don't remember.) If you need to hide two bits, use half of the co-efficients for one bit, and half for the other, and so on. Conversely, this method could also be extended to so that one bit is encoded into multiple blocks.
Rather than a keyed shuffle, I simply required the secret message to be strongly encrypted. This appears to have the added advantage of a message with predictable statistical properties.
Note also that robustness was not one of my criteria at the time.
Hope this is of some value (or at least interest). And my apologies if I have some of the terminology wrong - this was nearly twenty years ago and I don't have the work in front of me right now!