ok, the bug was with setting the wrong width and height for the rotation functions.
i've now updated the code. now it should work.
I am very sorry for this bug. was sure that i've fixed it before. i've now added the ability to also rotate by 180 degrees, so that you won't need to rotate twice (a little more efficient).
and just to say that the sample code wasn't for nothing, here's a nicer sample code.
it will go over all of your camera images, and rotate them in any of the 3 ways, and put the result files into Android/data/PACKAGE_NAME .
here's the code:
public class MainActivity extends Activity
{
@Override
protected void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final File picFolder=Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
final int screenWidth=getResources().getDisplayMetrics().widthPixels;
final int screenHeight=getResources().getDisplayMetrics().heightPixels;
final File outputDir=getExternalFilesDir(null);
final ProgressDialog progressDialog=ProgressDialog.show(this,"please wait","processing");
new AsyncTask<Void,Void,Void>()
{
@Override
protected Void doInBackground(final Void... params)
{
final File[] listFiles=outputDir.listFiles((FileFilter)null);
for(final File file : listFiles)
file.delete();
final List<String> imageFilesPaths=new ArrayList<String>();
getPicturesPaths(picFolder.getAbsolutePath(),imageFilesPaths);
final JniBitmapHolder bitmapHolder=new JniBitmapHolder();
int i=0;
final Options options=new Options();
for(final String filePath : imageFilesPaths)
{
options.inJustDecodeBounds=true;
options.inPreferredConfig=Config.ARGB_8888;
prepareForDownsampling(options,screenWidth,screenHeight);
Bitmap b=BitmapFactory.decodeFile(filePath,options);
bitmapHolder.storeBitmap(b);
b.recycle();
switch(i++%3)
{
case 0:
bitmapHolder.rotateBitmapCw90();
break;
case 1:
bitmapHolder.rotateBitmap180();
break;
case 2:
bitmapHolder.rotateBitmapCcw90();
break;
}
b=bitmapHolder.getBitmapAndFree();
final File imageFile=new File(outputDir.getAbsoluteFile()+File.separator+System.currentTimeMillis()+".jpg");
imageFile.getParentFile().mkdirs();
FileOutputStream stream=null;
try
{
stream=new FileOutputStream(imageFile);
b.compress(CompressFormat.JPEG,80,stream);
stream.flush();
stream.close();
}
catch(final Exception e)
{
e.printStackTrace();
}
finally
{
if(stream!=null)
try
{
stream.close();
}
catch(final IOException e)
{
e.printStackTrace();
}
}
}
return null;
}
@Override
protected void onPostExecute(final Void result)
{
super.onPostExecute(result);
progressDialog.dismiss();
finish();
}
}.execute();
}
private static void prepareForDownsampling(final Options bitmapOptions,final int reqWidth,final int reqHeight)
{
final int inSampleSize=calculateInSampleSize(bitmapOptions,reqWidth,reqHeight);
// as much as possible, use google's way to downsample:
bitmapOptions.inSampleSize=1;
bitmapOptions.inDensity=1;
bitmapOptions.inTargetDensity=1;
bitmapOptions.inJustDecodeBounds=false;
while(bitmapOptions.inSampleSize*2<=inSampleSize)
bitmapOptions.inSampleSize*=2;
// if google's way to downsample isn't enough, do some more :
if(bitmapOptions.inSampleSize!=inSampleSize)
{
// downsample by bitmapOptions.inSampleSize/originalSampleSize .
bitmapOptions.inTargetDensity=bitmapOptions.inSampleSize;
bitmapOptions.inDensity=inSampleSize;
}
}
public static int calculateInSampleSize(final BitmapFactory.Options options,final int reqWidth,final int reqHeight)
{
final int height=options.outHeight;
final int width=options.outWidth;
int inSampleSize=1;
if(height>reqHeight||width>reqWidth)
{
final int heightRatio=Math.round((float)height/(float)reqHeight);
final int widthRatio=Math.round((float)width/(float)reqWidth);
inSampleSize=heightRatio<widthRatio ? heightRatio : widthRatio;
}
return Math.max(inSampleSize,1);
}
private static void getPicturesPaths(final String path,final List<String> filesPaths)
{
final Options options=new Options();
options.inJustDecodeBounds=true;
File f=new File(path);
if(f.isFile())
{
BitmapFactory.decodeFile(path,options);
if(options.outHeight>=0&&options.outWidth>=0)
filesPaths.add(path);
return;
}
if(!f.isDirectory())
return;
final String[] childrenPaths=f.list();
for(final String fileName : childrenPaths)
{
if(fileName.startsWith("."))
continue;
f=new File(path+File.separator+fileName);
final String fullFilePath=f.getAbsolutePath();
if(f.isFile())
{
BitmapFactory.decodeFile(fullFilePath,options);
if(options.outHeight>=0&&options.outWidth>=0)
filesPaths.add(fullFilePath);
continue;
}
getPicturesPaths(fullFilePath,filesPaths);
}
}
}