I'm encrypting contents of a file by XORing it with a static key. Encrypting the contents varies from 100s to 200s on different android devices. Is there any way to speed up the process. Is there a way to speed up XORing bits?
byte[] buf = new byte[1024 * 1024];
byte[] cryptKey = AppUtil.KEY.getBytes();
int len;
while ((len = in.read(buf)) > 0) {
byte[] encryptedText = new byte[1024 * 1024];
for (int i = 0; i < buf.length; i++) {
encryptedText[i] = (byte) (buf[i] ^ cryptKey[i % AppUtil.KEY_SIZE]);
}
out.write(encryptedText, 0, len);
}
Since I'm working with arrays of byte, will it be better if i write this code in native? Also is there a better way than this.
Please do not suggest using AES or other algorithms. I'm not concerned with securing data, just preventing regular users from accessing specific directories of the app
Related
I'm relatively new to doing image compression on the byte level, and am currently working on a java image preprocessor that will take a bmp image, convert it to an 8-bit unsigned grayscale, then stack its bytes according to high and low before exporting and compressing it. After some extensive research and testing various methods of byte extraction, I'm still not seeing the results I need. Before I continue, it should be noted that all of these images are originally in DICOM format, and I'm using the ij.plugin.DICOM package to extract the pixel data as a bmp image.
The following description is represented by code bellow. Currently, I'm reading in the original image as a buffered image, converting it to grayscale, then getting the image bytes from the Raster. Then I take those bytes, and using some other code I found on stackoverflow and "converting" them to a String representation of binary bits. I then send that string to a character array. The next step might be extraneous, but I wanted to get your input before I removed it (since I'm new at this). I make a Bitset and iterate through the "binary" character array. If the character value is "1", I set that position in the BitSet to true. Then I send the BitSet to another byte array.
Then I make two new byte arrays, one for the high and one for the low byte. Using a for loop, I'm iterating over the "bit" array and storing every 4 "bits" in the high or low byte, depending on where we are in the array.
Lastly, I take the DICOM tag data, make a byte array from it, and then stack the tag array, the high byte array, and the low byte array together. My intended result is to have the image matrix be "split" with the top half containing all the high bytes and the bottom half containing all of the low bytes. I've been told that the tag bytes will be so small, they shouldn't affect the final outcome (I've tested the image without them, just to be sure, and there was no visible difference).
Below is the code. Please let me know if you have any questions, and I will modify my post accordingly. I've tried to include all relevant data. Let me know if you need more.
BufferedImage originalImage = getGrayScale(img.getBufferedImage());//returns an 8-bit unsigned grayscale conversion of the original image
byte[] imageInByte = ((DataBufferByte) originalImage.getRaster().getDataBuffer()).getData();
String binary = toBinary(imageInByte); //converts to a String representation of the binary bits
char[] binCharArray = binary.toCharArray();
BitSet bits = new BitSet(binCharArray.length);
for (int i = 0; i < binCharArray.length; i++) {
if (binCharArray[i] == '1') {
bits.set(i);
}
}
imageInByte = bits.toByteArray();
byte[] high = new byte[(int) imageInByte.length/2];
byte[] low = new byte[(int) imageInByte.length/2];
int highC = 0;
int lowC = 0;
boolean change = false; //start out storing in the high bit
//change will = true on very first run. While true, load in the high byte array. Else low byte
for(int i = 0; i < imageInByte.length; i++){
if(i % 4 == 0){
change = !change;
}
if(change){
high[highC] = imageInByte[i];
highC++;
} else {
low[lowC] = imageInByte[i];
lowC++;
}
}
//old code from a previous attempt.
// for (int j = 0; j < imageInByte.length; j++) {
// byte h = (byte) (imageInByte[j] & 0xFF);
// byte l = (byte) ((imageInByte[j] >> 8) & 0xFF);
// high[j] = h;
// low[j] = l;
// }
OutputStream out = null;
//add this array to the image array. It goes at the beginning.
byte[] tagBytes = dicomTags.getBytes();
currProcessingImageTagLength = tagBytes.length;
imageInByte = new byte[high.length + low.length + tagBytes.length];
System.arraycopy(tagBytes, 0, imageInByte, 0, tagBytes.length);
System.arraycopy(high, 0, imageInByte, tagBytes.length, high.length);
System.arraycopy(low, 0, imageInByte, tagBytes.length + high.length, low.length);
BufferedImage bImageFromConvert = new BufferedImage(dimWidth, dimHeight, BufferedImage.TYPE_BYTE_GRAY);//dimWidth and dimHeight are the image dimensions, stored much earlier in this function
byte[] bufferHolder = ((DataBufferByte) bImageFromConvert.getRaster().getDataBuffer()).getData();
System.arraycopy(imageInByte, 0, bufferHolder, 0, bufferHolder.length);
//This is where I try and write the final image before sending it off to an image compressor
ImageIO.write(bImageFromConvert, "bmp", new File(
directory + fileName + "_Compressed.bmp"));
return new File(directory + fileName + "_Compressed.bmp");
And below is the toBinary function in case you were interested:
private static String toBinary(byte[] bytes) {
StringBuilder sb = new StringBuilder(bytes.length * Byte.SIZE);
for (int i = 0; i < Byte.SIZE * bytes.length; i++) {
sb.append((bytes[i / Byte.SIZE] << i % Byte.SIZE & 0x80) == 0 ? '0' : '1');
}
return sb.toString();
}
Thank you so much for your help! I've spent nearly 20 hours now trying to solve this one problem. It's been a huge headache, and any insight you have would be appreciated.
EDIT: Here's the getGreyScale function:
public static BufferedImage getGrayScale(BufferedImage inputImage) {
BufferedImage img = new BufferedImage(inputImage.getWidth(), inputImage.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
Graphics g = img.getGraphics();
g.drawImage(inputImage, 0, 0, null);
g.dispose();
return img;
}
EDIT 2: I've added some images upon request.
Current output:
current image
Note, I can't post the images with the "expected" high byte and low byte outcome due to my reputation being lower than 10.
This says every 4 bytes change; thats not what you intend:
for(int i = 0; i < imageInByte.length; i++){
if(i % 4 == 0){
change = !change;
}
if(change){
high[highC] = imageInByte[i];
highC++;
} else {
low[lowC] = imageInByte[i];
lowC++;
}
}
I would replace it with this, from your earlier attempt
for (int j = 0; j < imageInByte.length; j+=2) {
byte h = (byte) (imageInByte[j] & 0xF0);
byte h2 = (byte) (imageInByte[j+1] & 0xF0);
byte l = (byte) (imageInByte[j] & 0x0f);
byte l2 = (byte) (imageInByte[j+1] & 0x0f);
high[j/2] = h|(h2>>4);
low[j/2] = (l<<4)|l2;
}
I did the code up to finding the PCM Data from a audio file. How should i apply these data to the Fast Fourier Transform Algorithm? Are there more things to consider before applying the byte array to FFT algorithm.
public static void main(String[] args) throws FileNotFoundException, IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
BufferedInputStream in = new BufferedInputStream(new FileInputStream("adios.wav"));
int read;
byte[] buff = new byte[1024];
while ((read = in.read(buff)) > 0)
{
out.write(buff, 0, read);
}
out.flush();
byte[] audioBytes = out.toByteArray();
for(int i=0; i<audioBytes.length;i++){
System.out.println(audioBytes[i]);
}
}
You need to skip the wav header and transform the PCM samples to float values between -1 and 1. For example for a byte array with PCM wav with 16 bits per sample and little endian the following conversion is needed (from com.sun.media.sound.AudioFloatConverter):
public float[] toFloatArray(byte[] in_buff, int in_offset,
float[] out_buff, int out_offset, int out_len) {
int ix = in_offset;
int len = out_offset + out_len;
for (int ox = out_offset; ox < len; ox++) {
out_buff[ox] = ((short) ((in_buff[ix++] & 0xFF) |
(in_buff[ix++] << 8))) * (1.0f / 32767.0f);
}
return out_buff;
}
After this call you end up with a float[] that can be used for an FFT analysis.
To make this more easy the JVM includes the AudioSystem and AudioInputStream classes.
The source code of TarsosDSP, a Java audio processing library, is full of examples. The TarosDSP manual explains the relation between PCM data and workable samples.
I am trying to figure out a way of taking data from a file and I want to store every 4 bytes as a bitset(32). I really have no idea of how to do this. I have played about with storing each byte from the file in an array and then tried to covert every 4 bytes to a bitset but I really cannot wrap my head around using bitsets. Any ideas on how to go about this?
FileInputStream data = null;
try
{
data = new FileInputStream(myFile);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int bytesRead;
while ((bytesRead = data.read(b)) != -1)
{
bos.write(b, 0, bytesRead);
}
byte[] bytes = bos.toByteArray();
Ok, you got your byte array. Now what you have to convert each byte to a bitset.
//Is number of bytes divisable by 4
bool divisableByFour = bytes.length % 4 == 0;
//Initialize BitSet array
BitSet[] bitSetArray = new BitSet[bytes.length / 4 + divisableByFour ? 0 : 1];
//Here you convert each 4 bytes to a BitSet
//You will handle the last BitSet later.
int i;
for(i = 0; i < bitSetArray.length-1; i++) {
int bi = i*4;
bitSetArray[i] = BitSet.valueOf(new byte[] { bytes[bi], bytes[bi+1], bytes[bi+2], bytes[bi+3]});
}
//Now handle the last BitSet.
//You do it here there may remain less than 4 bytes for the last BitSet.
byte[] lastBitSet = new byte[bytes.length - i*4];
for(int j = 0; j < lastBitSet.length; j++) {
lastBitSet[i] = bytes[i*4 + j]
}
//Put the last BitSet in your bitSetArray
bitSetArray[i] = BitSet.valueOf(lastBitSet);
I hope this works for you as I have written quickly and did not check if it works. But this gives you the basic idea, which was my intention at the beginning.
I am developing an application that uses mp3 encoding/decoding. While in principle it behaves correctly for most of the files, there are some exceptions. I detected that these files have a missing header. I get an array out of bound exception when attempting to decode. I used two approaches but both failed.
The first:
DecodedMpegAudioInputStream dais = (DecodedMpegAudioInputStream) AudioSystem.getAudioInputStream(daisf, ais);
byte[] audioData = IOUtils.toByteArray(dais);//exception here
And the second:
ByteOutputStream bos = new ByteOutputStream();
// Get the decoded stream.
byte[] byteData = new byte[1];
int nBytesRead = 0;
int offset = 0;
int cnt=1;
while (nBytesRead != -1) {
System.out.println("cnt="+cnt);
nBytesRead = dais.read(byteData, offset, byteData.length);//exception here at first loop
if (nBytesRead != -1) {
int numShorts = nBytesRead >> 1;
for (int j = 0; j < numShorts; j++) {
bos.write(byteData[j]);
}
}
cnt+=1;
}
byte[] audioData = bos.getBytes();
It seems that there is an issue with the headers or the structure of it, because the dais stream has content/bytes. However it can be opened with audacity and ffplay so I believe there should be a workaround. Any ideas how to counter it?
You could use code redundancy to improve reliability. Look into alternative libraries, such as Xuggler or JLayer.
I'm having some issues taking audio data stored in a byte array, converting it to a big-endian short array, encoding it, then changing it back into a byte array. Here is what I have. The original audio data is stored in audioBytes2. I am using the same format for decode with a minus on the cos function instead. Unfortunately, changing the byte and short data types is non-negotiable.
short[] audioData = null;
int nlengthInSamples = audioBytes2.length / 2;
audioData = new short[nlengthInSamples];
for (int i = 0; i < nlengthInSamples; i++) {
short MSB = (short) audioBytes2[2*i+1];
short LSB = (short) audioBytes2[2*i];
audioData[i] = (short) (MSB << 8 | (255 & LSB));
}
int i = 0;
while (i < audioData.length) {
audioData[i] = (short)(audioData[i] + (short)5*Math.cos(2*Math.PI*i/(((Number)EncodeBox.getValue()).intValue())));
i++;
}
short x = 0;
i = 0;
while (i < audioData.length) {
x = audioData[i];
audioBytes2[2*i+1] = (byte)(x >>> 0);
audioBytes2[2*i] = (byte)(x >>> 8);
i++;
}
I have done everything that I can think of to make this work, but the closest I've come is getting it to work every other encode/decode and I have no idea why. Thanks for any help.
I also suggest you try ByteBuffer.
byte[] bytes = {};
short[] shorts = new short[bytes.length/2];
// to turn bytes to shorts as either big endian or little endian.
ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(shorts);
// to turn shorts back to bytes.
byte[] bytes2 = new byte[shortsA.length * 2];
ByteBuffer.wrap(bytes2).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().put(shortsA);
public short bytesToShort(byte[] bytes) {
return ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getShort();
}
public byte[] shortToBytes(short value) {
return ByteBuffer.allocate(2).order(ByteOrder.LITTLE_ENDIAN).putShort(value).array();
}
How about some ByteBuffers?
byte[] payload = new byte[]{0x7F,0x1B,0x10,0x11};
ByteBuffer bb = ByteBuffer.wrap(payload).order(ByteOrder.BIG_ENDIAN);
ShortBuffer sb = bb.asShortBuffer();
while(sb.hasRemaining()){
System.out.println(sb.get());
}
byte[2] bytes;
int r = bytes[1] & 0xFF;
r = (r << 8) | (bytes[0] & 0xFF);
short s = (short)r;
Your code is doing little-endian shorts, not big. You've the indexing for MSB and LSB swapped.
Since you are using big-endian shorts, you could be using a DataInputStream wrapped around a ByteArrayInputStream (and DataOutputStream/ByteArrayOutputStream) on the other end, rather than doing your own decoding.
If you're getting every other decode working, I'd guess you've got an odd number of bytes, or an off-by-one error elsewhere which is causing your mistake to get fixed on every other pass.
Finally, I'd step through the array with i+=2 and use MSB= arr[i] and LSB=arr[i+1] rather than multiplying by 2, but that's just me.
It looks like you are swapping the byte order between reading the bytes in and writing them back out (unsure if this is intentional or not).