Kinect background removal - kinect

I followed the code provided by Robert Levy at this link: http://channel9.msdn.com/coding4fun/kinect/Display-Kinect-color-image-containing-only-players-aka-background-removal
I tried implementing it into my existing code, and have had inconsistent results. If the user is in the kinect's field of view when the program starts up it will remove the background some of the time. If the user walks into the field of view it will not pick them up.
namespace KinectUserRecognition
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
//Kinect Runtime
Runtime kinect = Runtime.Kinects[0];
PlanarImage colorImage;
PlanarImage depthImage;
bool isDepthImage;
WriteableBitmap player1;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
isDepthImage = false;
//UseDepthAndPlayerIndex and UseSkeletalTracking
kinect.Initialize(RuntimeOptions.UseDepthAndPlayerIndex | RuntimeOptions.UseColor);// | RuntimeOptions.UseSkeletalTracking);
//register for event
kinect.VideoFrameReady += new EventHandler<ImageFrameReadyEventArgs>(nui_VideoFrameReady);
kinect.DepthFrameReady += new EventHandler<ImageFrameReadyEventArgs>(nui_DepthFrameReady);
//Video image type
kinect.VideoStream.Open(ImageStreamType.Video, 2, ImageResolution.Resolution640x480,
ImageType.Color);
//DepthAndPlayerIndex ImageType
kinect.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution320x240,
ImageType.DepthAndPlayerIndex);
}
void nui_VideoFrameReady(object sender, ImageFrameReadyEventArgs e)
{
colorImage = e.ImageFrame.Image;
image1.Source = BitmapSource.Create(colorImage.Width, colorImage.Height, 96, 96,
PixelFormats.Bgr32, null, colorImage.Bits, colorImage.Width * colorImage.BytesPerPixel);
if (isDepthImage)
{
player1 = GeneratePlayerImage(e.ImageFrame, 1);
image3.Source = player1;
}
}
void nui_DepthFrameReady(object sender, ImageFrameReadyEventArgs e)
{
//Convert depth information for a pixel into color information
byte[] ColoredBytes = GenerateColoredBytes(e.ImageFrame);
depthImage = e.ImageFrame.Image;
image2.Source = BitmapSource.Create(depthImage.Width, depthImage.Height, 96, 96, PixelFormats.Bgr32, null,
ColoredBytes, depthImage.Width * PixelFormats.Bgr32.BitsPerPixel / 8);
isDepthImage = true;
}
private WriteableBitmap GeneratePlayerImage(ImageFrame imageFrame, int playerIndex)
{
int depthWidth = kinect.DepthStream.Width;
int depthHeight = kinect.DepthStream.Height;
WriteableBitmap target = new WriteableBitmap(depthWidth, depthHeight, 96, 96, PixelFormats.Bgra32, null);
var depthRect = new System.Windows.Int32Rect(0, 0, depthWidth, depthHeight);
byte[] color = imageFrame.Image.Bits;
byte[] output = new byte[depthWidth * depthHeight * 4];
//loop over each pixel in the depth image
int outputIndex = 0;
for (int depthY = 0, depthIndex = 0; depthY < depthHeight; depthY++)
{
for(int depthX = 0; depthX < depthWidth; depthX++, depthIndex +=2)
{
short depthValue = (short)(depthImage.Bits[depthIndex] | (depthImage.Bits[depthIndex + 1] << 8));
int colorX, colorY;
kinect.NuiCamera.GetColorPixelCoordinatesFromDepthPixel(
imageFrame.Resolution,
imageFrame.ViewArea,
depthX, depthY, //depth coordinate
depthValue, //depth value
out colorX, out colorY); //color coordinate
//ensure that the calculate color location is within the bounds of the image
colorX = Math.Max(0, Math.Min(colorX, imageFrame.Image.Width - 1));
colorY = Math.Max(0, Math.Min(colorY, imageFrame.Image.Height - 1));
output[outputIndex++] = color[(4 * (colorX + (colorY * imageFrame.Image.Width))) + 0];
output[outputIndex++] = color[(4 * (colorX + (colorY * imageFrame.Image.Width))) + 1];
output[outputIndex++] = color[(4 * (colorX + (colorY * imageFrame.Image.Width))) + 2];
output[outputIndex++] = GetPlayerIndex(depthImage.Bits[depthIndex]) == playerIndex ? (byte)255 : (byte)0;
}
}
target.WritePixels(depthRect, output, depthWidth * PixelFormats.Bgra32.BitsPerPixel / 8, 0);
return target;
//return output;
}
private static int GetPlayerIndex(byte firstFrame)
{
//returns 0 = no player, 1 = 1st player, 2 = 2nd player...
//bitwise & on firstFrame
return (int)firstFrame & 7;
}
}
}
-Edit 1-
I think I've narrowed the problem down, but I'm not sure of a way to resolve it. I assumed that having only one person in the kinect's field of view would return a value of one from my "GetPlayerIndex" method. This is not the case. I was hoping to produce a separate image for each person with the background removed. What type of values should I assume to receive from:
-Edit 2-
From my tests I've noticed that I can a max value of 6 for the player index, but the index that I get isn't consistent. If there a way to know what player index will be assigned to a skeleton? For example, if I were the only person in the fov would there be a way to know that my player index would always be 1?

The player index is not guaranteed to be anything. Once it catches a skeleton, the index will stay the same for that skeleton until it loses sight of it, but you can't assume that the first player will be 1, the second 2, etc.
What you'll need to do is determine a valid skeleton index prior to the player1 = GeneratePlayerImage(e.ImageFrame, 1); call, or alter the GeneratePlayerImage function to find an index. If you're only interested in removing the background and leaving the pixels for all the people in the frame untouched, just change this:
output[outputIndex++] = GetPlayerIndex(depthImage.Bits[depthIndex]) == playerIndex ? (byte)255 : (byte)0;
to this, which will just check for ANY player, instead of a specific player:
output[outputIndex++] = GetPlayerIndex(depthImage.Bits[depthIndex]) != 0 ? (byte)255 : (byte)0;
The other two ways I can think of to do this for a specific player instead of all players:
Open the Kinect's Skeleton feed, and loop through the array of skeletons it gives you to find a valid index. Create a global integer to hold this index, then call the GeneratePlayerImage method with this global integer.
Change the GeneratePlayerImage method to check for a player index in each pixel, and if one is found use that index to remove the background for the entire image (ignore any other index it finds).

Related

Script command to Align Slice Horizontally by Calibration

Is there a script command that I can specify a particular slice in a LinePlotImageDisplay and do the Align Slice Horizontally by Calibration (or Uncalibrated (channels)) action?
The following scipt is a complete implantation based on example codes provided by BmyGuest. It will align all slices in a LinePlotImageDisplay horizontally either by calibration or by channel (i.e. un-calibrated).
class SliceAlignment : object {
number true, false; // boolean
image imgLPID;
imageDisplay LPID; // line plot image display
number CalculateImageToGroupTransformFactors( object self, image slice_src, image slice_ref, number &relOff, number &relScale ) {
number origin_ref, scale_ref, origin_src, scale_src;
string unit_ref, unit_src;
number calFMT = 0; // origin is expressed in calibrated unit
//
slice_src.ImageGetDimensionCalibration( 0, origin_src, scale_src, unit_src, calFMT );
slice_ref.ImageGetDimensionCalibration( 0, origin_ref, scale_ref, unit_ref, calFMT );
//
relScale = scale_src / scale_ref;
relOff = (origin_src - origin_ref) / scale_ref ;
// check if both images are calibrated in same unit
if( unit_src != unit_ref ) return false
return true;
};
void AlignNthSliceHorizontallyByChannel( object self, number slice_idx ) {
// get current reference slice index
number refSlice_idx = LPID.LinePlotImageDisplayGetSlice();
// get slice ID's (as objects)
object slice_ref = LPID.ImageDisplayGetSliceIDByIndex(refSlice_idx);
object slice_src = LPID.ImageDisplayGetSliceIDByIndex(slice_idx);
number int_offset = 0, int_scale = 1.0; // vertical (intensity) offset and scaling factors
number pos_offset = 0, pos_scale = 1.0; // horizontal (position) offset and scaling factors
LPID.LinePlotImageDisplaySetImageToGroupTransform( slice_src, slice_ref, int_offset, int_scale, pos_offset, pos_scale );
};
void AlignNthSliceHorizontallyByCalibration( object self, number slice_idx ) {
// get current reference slice index
number refSlice_idx = LPID.LinePlotImageDisplayGetSlice();
// get slice ID's (as objects)
object slice_ref = LPID.ImageDisplayGetSliceIDByIndex(refSlice_idx);
object slice_src = LPID.ImageDisplayGetSliceIDByIndex(slice_idx);
number int_offset = 0, int_scale = 1.0; // vertical (intensity) offset and scaling factors
number pos_offset, pos_scale; // horizontal (position) offset and scaling factors
number unit_check = self.CalculateImageToGroupTransformFactors( imgLPID{slice_idx}, imgLPID{refSlice_idx}, pos_offset, pos_scale );
if( unit_check == false ) {
string prompt = "slice #" + slice_idx + " [" + LPID.ImageDisplayGetSliceLabelById( LPID.ImageDisplayGetSliceIDByIndex(slice_idx) ) + "] is calibrated in different unit!";
if( !ContinueCancelDialog( prompt ) ) return
};
LPID.LinePlotImageDisplaySetImageToGroupTransform( slice_src, slice_ref, int_offset, int_scale, pos_offset, pos_scale );
return;
};
void AlignAllSlicesHorizontallyByChannel( object self ) {
number nSlices = LPID.LinePlotImageDisplayCountSlices();
for( number idx = 0; idx < nSlices; idx++ ) self.AlignNthSliceHorizontallyByChannel( idx );
return;
};
void AlignAllSlicesHorizontallyByCalibration( object self ) {
number nSlices = LPID.LinePlotImageDisplayCountSlices();
for( number idx = 0; idx < nSlices; idx++ ) self.AlignNthSliceHorizontallyByCalibration( idx );
return;
};
object init( object self, image img ) {
// check if the image display is correct type
imgLPID := img;
LPID = imgLPID.ImageGetImageDisplay(0);
if( LPID.ImageDisplayGetDisplayType() != 3 ) throw( "Please choose a valid line plot display" );
return self;
};
SliceAlignment( object self ) {
true = 1; false = 0;
result( "SliceAlignment [obj ID:" + self.ScriptObjectGetID().hex() + "] constructured\n" );
};
~SliceAlignment( object self ) {
result( "SliceAlignment [obj ID:" + self.ScriptObjectGetID().hex() + "] destructured\n\n" );
}; };
{; object objAlign = alloc(SliceAlignment);
objAlign.init( GetFrontImage() );
if( OptionDown() ) objAlign.AlignAllSlicesHorizontallyByChannel();
else objAlign.AlignAllSlicesHorizontallyByCalibration(); };
No, there is no single 'convenience' command to achieve this alignment. You will have to create the according function yourself from reading a slices calibration and setting its display-coordinate system. You might find the following (old) tutorial PDF on the FELMI homepage might be useful:
SlicesInLinePlotDisplay.pdf
The following example script might also be useful. It shows how one slice is aligned relative to another slice. (Just on the X-axis)
// All Slices in a LinePlot are grouped into a single 'group'
// Slices can be moved relative to each other by specifying their image-to-group transform,
// and the whole image (i.e. the group) can be moved with respect to the display using the group-to-display transform.
// To set the image-to-group transform of the slice specified by 'slice_id', with respect to the slice specified by 'ref_id'
// use the command:
// LinePlotImageDisplaySetImageToGroupTransform( LinePlotImageDisplay lpid, ScriptObject slice_id, ScriptObject ref_id, double off_val, double scale_val, double off_dim_0, double scale_dim_0 )
/*********************************************************/
// Create 2 LinePlots and add them into one display
// (Initially they are aligned by their calibrations)
number sc1 = 1
number of1 = -50
number sc2 = 2
number of2 = -20
image sl1 := realImage("S1",4,300)
image sl2 := realImage("S2",4,300)
sl1 = (iwidth-icol)/iwidth
sl2 = (iwidth-icol)/iwidth
sl1[0,50,1,60] = 1
sl1[0,250,1,260] = 1
sl2[0,10,1,15] = 1
sl2[0,110,1,115] = 1
// Adding Calibrations
sl1.ImageSetDimensionCalibration(0,of1,sc1,"CH",0)
sl2.ImageSetDimensionCalibration(0,of2,sc2,"CH",0)
sl1.DisplayAt(20,30)
sl2.DisplayAt(750,30)
OKDialog( "Put into one Display" )
imageDisplay disp = sl1.ImageGetImageDisplay(0)
disp.ImageDisplayAddImage( sl2, "S2") // When added like this, the slices are automatically aligned by their respective calibration!
disp.LinePlotImageDisplaySetDoAutoSurvey( 0, 0 )
object ref_id = disp.ImageDisplayGetSliceIDByIndex(0) // Slice 0
object slice_id = disp.ImageDisplayGetSliceIDByIndex(1) // Slice 1
OKDialog("Now align by channels (i.e. undo any relative sclice alignment)")
// Simply set the relative "shifts" and "scales" to 0 and 1.
disp.LinePlotImageDisplaySetImageToGroupTransform( slice_id, ref_id, 0, 1, 0, 1 )
OKDialog("Now align by chalibration ")
number relScale = sc2/sc1
number relOff = of2-of1
disp.LinePlotImageDisplaySetImageToGroupTransform( slice_id, ref_id, 0, 1, relOff, relScale )

Windows Store App: set an image as a background for an UI element

Sorry for asking a really basic question, but it's probably the first time for a number of years I feel really confused.
Windows provides two set of controls: Windows.UI.Xaml namespace (I thinks this is referred as Metro), used for Windows Store Apps, and System.Windows (WPF) for Desktop.
Since I am going to develop Windows Store Apps mainly for Windows 8.1 and Windows 10 phones, I will have to stick to Windows.UI.Xaml, and this has not only a separate set of UI elements, but also separate set of bitmaps, brushes, etc. (Windows.UI.Xaml.Media vs System.Windows.Media).
I found that Windows.UI.Xaml provides a very limited support for graphics, much less than provided by WPF, Android or (even!) iOS platform. To start with, I got stuck with a simple task: tiling a background!
Since Windows.UI.Xaml.Media.ImageBrush do not support tiling, I wanted to to do that "manually". Some sites suggest making numerous number of children, each holding a tile. Honestly, it looks as a rather awkward approach to me, so I decided to do it in what appears a more natural way: create an off-screen tiled image, assign it to a brush and assign the brush as the background for a panel.
The tiling code is rather straightforward (it probably has mistakes, possibly won't even not run on a phone, because of some unavailable classes used).
int panelWidth = (int) contentPanel.Width;
int panelHeight = (int) contentPanel.Height;
Bitmap bmpOffscreen = new Bitmap(panelWidth, panelHeight);
Graphics gOffscreen = Graphics.FromImage(bmpOffscreen);
string bmpPath = Path.Combine(Windows.ApplicationModel.Package.Current.InstalledLocation.Path, "Assets/just_a_tile.png");
System.Drawing.Image tile = System.Drawing.Image.FromFile(bmpPath, true);
int tileWidth = tile.Width;
int tileHeight = tile.Height;
for (int y = 0; y < panelHeight; y += tileHeight)
for (int x = 0; x < panelWidth; x += tileWidth)
gOffscreen.DrawImage(tile, x, y);
Now I presumably have the tiled image in bmpOffscreen. But how assign it to a brush? To do that I need to convert Bitmap to BitmapSource, while I couldn't find something similar to System.Windows.Imaging.CreateBitmapSourceFromHBitmap available for WPF structure!
Well, first of all System.Drawing namespace is not available in Windows Universal Platform, so you won't be able to use Bitmap class
But, all hope is not lost - you can use
Windows.UI.Xaml.Media.Imaging.WriteableBitmap
If you look at example included on this page, you will see that at one point image data is extracted to a byte array - all you need to do is copy it according to your needs
Please let me know if you want me to include a complete code sample.
Edit:
StorageFile file = await StorageFile.GetFileFromPathAsync(filePath);
Scenario4WriteableBitmap = new WriteableBitmap(2000, 2000);
// Ensure a file was selected
if (file != null)
{
using (IRandomAccessStream fileStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read))
{
int columns = 4;
int rows = 4;
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(fileStream);
// Scale image to appropriate size
BitmapTransform transform = new BitmapTransform()
{
ScaledHeight = Convert.ToUInt32(Scenario4ImageContainer.Height),
ScaledWidth = Convert.ToUInt32(Scenario4ImageContainer.Width)
};
PixelDataProvider pixelData = await decoder.GetPixelDataAsync(
BitmapPixelFormat.Bgra8, // WriteableBitmap uses BGRA format
BitmapAlphaMode.Straight,
transform,
ExifOrientationMode.IgnoreExifOrientation, // This sample ignores Exif orientation
ColorManagementMode.DoNotColorManage);
// An array containing the decoded image data, which could be modified before being displayed
byte[] sourcePixels = pixelData.DetachPixelData();
// Open a stream to copy the image contents to the WriteableBitmap's pixel buffer
using (Stream stream = Scenario4WriteableBitmap.PixelBuffer.AsStream())
{
for (int i = 0; i < columns * rows; i++)
{
await stream.WriteAsync(sourcePixels, 0, sourcePixels.Length);
}
}
}
// Redraw the WriteableBitmap
Scenario4WriteableBitmap.Invalidate();
Scenario4Image.Source = Scenario4WriteableBitmap;
Scenario4Image.Stretch = Stretch.None;
}
Thank you, Arkadiusz. Since Australian time goes slightly ahead of Europe,
I had an advantage and seen the code before you posted it. I downloaded
MSDN XAML images sample and it helped me a lot. I gave a +1 to you but someone apparently put -1, so it compensated each other. Don't be upset I get -1 so often, that I stopped paying attention on that :)
So I've managed to do tiling with Windows Universal Platform! On my Lumia 532 phone it works magnifique. I felt like re-inventing a wheel, because all this stuff must be handled by SDK, not by a third-party developer.
public static async Task<bool> setupTiledBackground(Panel panel, string tilePath)
{
Brush backgroundBrush = await createTiledBackground((int)panel.Width, (int)panel.Height, TilePath);
if (backgroundBrush == null) return false;
panel.Background = backgroundBrush;
return true;
}
private static async Task<Brush> createTiledBackground(int width, int height, string tilePath)
{
StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///" + tilePath));
byte[] sourcePixels;
int tileWidth, tileHeight;
using (IRandomAccessStream inputStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read))
{
if (inputStream == null) return null;
BitmapDecoder tileDecoder = await BitmapDecoder.CreateAsync(inputStream);
if (tileDecoder == null) return null;
tileWidth = (int)tileDecoder.PixelWidth;
tileHeight = (int) tileDecoder.PixelHeight;
PixelDataProvider pixelData = await tileDecoder.GetPixelDataAsync(
BitmapPixelFormat.Bgra8, // WriteableBitmap uses BGRA format
BitmapAlphaMode.Straight,
new BitmapTransform(),
ExifOrientationMode.IgnoreExifOrientation,
ColorManagementMode.DoNotColorManage);
sourcePixels = pixelData.DetachPixelData();
// fileStream.Dispose();
}
WriteableBitmap backgroundBitmap = new WriteableBitmap(width, height);
int tileBmpWidth = tileWidth << 2;
int screenBmpWidth = width << 2;
int tileSize = tileBmpWidth * tileHeight;
int sourceOffset = 0;
using (Stream outputStream = backgroundBitmap.PixelBuffer.AsStream())
{
for (int bmpY=0; bmpY < height; bmpY++) {
for (int bmpX = 0; bmpX < screenBmpWidth; bmpX += tileBmpWidth)
await outputStream.WriteAsync(sourcePixels, sourceOffset, Math.Min(screenBmpWidth - bmpX, tileBmpWidth));
if ((sourceOffset += tileBmpWidth) >= tileSize)
sourceOffset -= tileSize;
}
}
ImageBrush backgroundBrush = new ImageBrush();
backgroundBrush.ImageSource = backgroundBitmap; // It's very easy now!
return backgroundBrush; // Finita la comédia!
}
Just one remark: if you do it on form start, you should not wait for it.
This doesn't work:
public MainPage()
{
this.InitializeComponent();
bool result = setupTiledBackground(contextPanel, TilePath).Result;
}
This works:
private Task<bool> backgroundImageTask;
public MainPage()
{
this.InitializeComponent();
backgroundImageTask = setupTiledBackground(contextPanel, TilePath);
}

Making sense of a list of GPS values in an iOS application

I have a web service that interfaces with the google maps API to generate a polygon on a google map. The service takes the GPS values and stores them for retrieval.
The problem is that when I try and use these values on my iPhone app the MKPolyline is just either a mess or a bunch of zig-zag lines.
Is there a way to make sense of these values so I can reconstruct the polygon?
My current code looks like this
private void GenerateMap()
{
var latCoord = new List<double>();
var longCoord = new List<double>();
var pad = AppDelegate.Self.db.GetPaddockFromCrop(crop);
mapMapView.MapType = MKMapType.Standard;
mapMapView.ZoomEnabled = true;
mapMapView.ScrollEnabled = false;
mapMapView.OverlayRenderer = (m, o) =>
{
if (o.GetType() == typeof(MKPolyline))
{
var p = new MKPolylineRenderer((MKPolyline)o);
p.LineWidth = 2.0f;
p.StrokeColor = UIColor.Green;
return p;
}
else
return null;
};
scMapType.ValueChanged += (s, e) =>
{
switch (scMapType.SelectedSegment)
{
case 0:
mapMapView.MapType = MKMapType.Standard;
break;
case 1:
mapMapView.MapType = MKMapType.Satellite;
break;
case 2:
mapMapView.MapType = MKMapType.Hybrid;
break;
}
};
if (pad.Boundaries != null)
{
var bounds = pad.Boundaries.OrderBy(t => t.latitude).ThenBy(t => t.longitude).ToList();
foreach (var l in bounds)
{
double lat = l.latitude;
double lon = l.longitude;
latCoord.Add(lat);
longCoord.Add(lon);
}
if (latCoord.Count != 0)
{
if (latCoord.Count > 0)
{
var coord = new List<CLLocationCoordinate2D>();
for (int i = 0; i < latCoord.Count; ++i)
{
var c = new CLLocationCoordinate2D();
c.Latitude = latCoord[i];
c.Longitude = longCoord[i];
coord.Add(c);
}
var line = MKPolyline.FromCoordinates(coord.ToArray());
mapMapView.AddOverlay(line);
mapMapView.SetVisibleMapRect(line.BoundingMapRect, true);
}
}
}
}
MKPolygon / MKPolygonRenderer gives the same sort of random line mess. The OrderBy LINQ makes no difference other than to make the random lines a zig-zag going up or down the view.
Since you don't know the order the points were captured in, you can't trace the actual path traveled around the perimeter of the paddock; this is why your polylines are turning into silly-walks all over the map. Lacking that information, you can at best make an educated guess.
Some possible heuristics you might want to try:
Take the average of all the points to get a "somewhere in the middle" point, then order by atan2(l.latitude - middle.latitude, l.longitude - middle.longitude). (Be careful, atan2 is undefined at (0, 0)!)
Take the convex hull of the points captured: for a relatively small number of points you can get away with the simple quadratic time Jarvis's march. This has the approximate effect of wrapping a notional rubber band around the outside of the map push-pins by discarding points that would form concavities, and should also give you the order of the remaining points.

How to make a simple screenshot method using LWJGL?

So basically I was messing about with LWJGL for a while now, and I came to a sudden stop with with annoyances surrounding glReadPixels().
And why it will only read from left-bottom -> top-right.
So I am here to answer my own question since I figured all this stuff out, And I am hoping my discoveries might be of some use to someone else.
As a side-note I am using:
glOrtho(0, WIDTH, 0 , HEIGHT, 1, -1);
So here it is my screen-capture code which can be implemented in any LWJGL application C:
//=========================getScreenImage==================================//
private void screenShot(){
//Creating an rbg array of total pixels
int[] pixels = new int[WIDTH * HEIGHT];
int bindex;
// allocate space for RBG pixels
ByteBuffer fb = ByteBuffer.allocateDirect(WIDTH * HEIGHT * 3);
// grab a copy of the current frame contents as RGB
glReadPixels(0, 0, WIDTH, HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, fb);
BufferedImage imageIn = new BufferedImage(WIDTH, HEIGHT,BufferedImage.TYPE_INT_RGB);
// convert RGB data in ByteBuffer to integer array
for (int i=0; i < pixels.length; i++) {
bindex = i * 3;
pixels[i] =
((fb.get(bindex) << 16)) +
((fb.get(bindex+1) << 8)) +
((fb.get(bindex+2) << 0));
}
//Allocate colored pixel to buffered Image
imageIn.setRGB(0, 0, WIDTH, HEIGHT, pixels, 0 , WIDTH);
//Creating the transformation direction (horizontal)
AffineTransform at = AffineTransform.getScaleInstance(1, -1);
at.translate(0, -imageIn.getHeight(null));
//Applying transformation
AffineTransformOp opRotated = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
BufferedImage imageOut = opRotated.filter(imageIn, null);
try {//Try to screate image, else show exception.
ImageIO.write(imageOut, format , fileLoc);
}
catch (Exception e) {
System.out.println("ScreenShot() exception: " +e);
}
}
I hope this has been useful.
For any questions or comments on the code, ask/suggest as you like. C:
Hugs,
Rose.
sorry for the late reply but this is for anybody still looking for a solution.
public static void saveScreenshot() throws Exception {
System.out.println("Saving screenshot!");
Rectangle screenRect = new Rectangle(Display.getX(), Display.getY(), Display.getWidth(), Display.getHeight());
BufferedImage capture = new Robot().createScreenCapture(screenRect);
ImageIO.write(capture, "png", new File("doc/saved/screenshot.png"));
}

Resizing Jtable column widths wont work

//can set column widths using percentages
private void setPreferredTableColumnWidths(JTable table, double[] percentages)
{
Dimension tableDim = table.getSize();
double total = 0;
for(int i = 0; i < table.getColumnModel().getColumnCount(); i++)
total += percentages[i];
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
for(int i = 0; i < table.getColumnModel().getColumnCount(); i++)
{
TableColumn column = table.getColumnModel().getColumn(i);
column.setPreferredWidth((int) (tableDim.width * (percentages[i] / total)));
}
}
I want to be able to change the widths of a JTable based on a percentage of the total width of the table. The above code looks like it should work, but I only get equal width columns when I call it using "setPreferredTableColumnWidths(table, new double[] {.01,.4,.2,.2,.2});"
What could be the problem?
Try to add the line:
table.doLayout();
At the end of the method.
Your code works fine but depending on where you call it the table may or may not have a width. In the constructor of a Panel (or whatever contains the table) there is not width yet.
I put the call to your method in the paint() method. But be sure to keep track and only call it once or it will resize the columns over and over.
#Override
public void paint(Graphics g) {
super.paint(g);
if(! this.initialSizeSet){
this.setPreferredTableColumnWidths(this.table, new double[] {0.1, 0.1, 0.5, 0.3});
this.initialSizeSet = true;
}
}