ITextSharp - get image at a particular location - image

What I need to do is extract a 2D DataMatrix (bitmap) bar code and read it. I can make this work however, I have to loop through all the images on every page. This is taking a long time when I have 1000’s of pages, so I was wondering if it was possible to define a location(rectangle)of where the image(barcode) was and just extract that image?
The bar code is always i the same location.
note: I'm using Spire.Barcode from e-IceBlue
Thank you for any help.
CODE RenderFilter snippet:
public class MyRegionTextRenderFilter : RenderFilter {
/** the region to allow text from */
private RectangleJ filterRect;
public PdfImageObject image;
/**
* Constructs a filter
* #param filterRect the rectangle to filter text against. Note that this is a java.awt.Rectangle !
*/
public MyRegionTextRenderFilter(RectangleJ filterRect) {
this.filterRect = filterRect;
}
/**
* Constructs a filter
* #param filterRect the rectangle to filter text against.
*/
public MyRegionTextRenderFilter(iTextSharp.text.Rectangle filterRect)
{
this.filterRect = new RectangleJ(filterRect);
}
/**
* #see com.itextpdf.text.pdf.parser.RenderFilter#allowText(com.itextpdf.text.pdf.parser.TextRenderInfo)
*/
public override bool AllowImage(ImageRenderInfo renderInfo)
{
var matrix = renderInfo.GetImageCTM();
float left = matrix[6];
float top = matrix[7];
float width = matrix[0];
float height = matrix[4];
return filterRect.IntersectsLine(left, top, width, height);
}
}
Code calling :
RectangleJ rect = new RectangleJ(518.0f, 18.0f, 23.0f, 23.0f);
PdfReaderContentParser parser2 = new PdfReaderContentParser(pdfReader);
RenderFilter[] renderFilter = new RenderFilter[1];
renderFilter[0] = new MyRegionTextRenderFilter(rect);
FilteredTextRenderListener listener2 = new FilteredTextRenderListener(new LocationTextExtractionStrategy(), renderFilter);
parser2.ProcessContent(3, listener2);

The parser namespace of iText(Sharp) allows filtering of information digested by an IRenderListener implementation by using a RenderFilter:
public abstract class RenderFilter {
/**
* #param renderInfo
* #return true if the text render operation should be performed
*/
public virtual bool AllowText(TextRenderInfo renderInfo){
return true;
}
/**
*
* #param renderInfo
* #return true is the image render operation should be performed
*/
public virtual bool AllowImage(ImageRenderInfo renderInfo){
return true;
}
}
For filtering by area there already is a textual render filter, the RegionTextRenderFilter.
For your task simply copy it and add an AllowImage(ImageRenderInfo renderInfo) implementation similar to the existing AllowText(TextRenderInfo renderInfo) method.

Related

ES6 inherited function returns wrong type when invoked on subclass

When a function is inherited by a subclass, I want the return type to be as if the function were defined directly on the subclass.
To be clear, the code works fine at run-time. But I want to take advantage of static type-checking. I'm getting red squiggly lines in VScode and warnings from Google-Closure-Compiler. I'm not sure if this is an issue with my ES6 code or with my type annotations.
My trivial example ES6 classes:
// #ts-check
"use strict";
export class db_row {
/**
* #param {number} id
*/
constructor(id) {
/** #type {number} */
this.id = id;
}
clone() {
return new db_row(this.id);
}
}
export class Channel_row extends db_row {
/**
* Constructor
* #param {*=} init
* #param {string=} name
* #param {string=} value
*/
constructor(init, name, value = '') {
let id = -1;
if (typeof init == 'object') {
id = init.id;
name = init.name;
value = init.value;
} else if (typeof init == 'number') {
id = init;
}
super(id);
this.name = name;
this.value = value;
}
clone() {
return new Channel_row(this.id, this.name, this.value);
}
}
export class db_table {
/**
* Constructor
* #param {Array<db_row>} table
*/
constructor(table) {
/**#type {Array<db_row>} */
this.table = table;
}
/**
*/
get_table_copy() { return this.table.map(item => item.clone()) }
/**
* #param {?number=} id
*/
get_row_by_id(id) {
const row = this.table.filter(item => item.id === id)[0];
if (row) return row.clone();
return null;
}
}
export class Channel_table extends db_table {
constructor() {
/**#type {Array<Channel_row>} */
let table = [];
super(table);
}
}
// Test code below:
/**
*
* #param {Channel_row} chan_row
*/
function print_chan_row(chan_row) {
console.log(chan_row.name);
}
let channel_table = new Channel_table();
let channel_row = channel_table.get_row_by_id(0); // hover reports that the type of channel_row is db_row, when it should be type Channel_row
print_chan_row(channel_row); // Red squiggly line error: Argument of type 'db_row' is not assignable to parameter of type 'Channel_row'. Type 'db_row' is missing the following properties from type 'Channel_row': name, valuets(2345)
console.log(channel_row.name); // Red squiggly line error: Property 'name' does not exist on type 'db_row'.ts(2339)
let channel_table_2 = channel_table.get_table_copy(); // hover reports that the type of channel_row is db_row[], when it should be type Channel_row[]
print_chan_row(channel_table_2[0]); // Red squiggly line error: Argument of type 'db_row' is not assignable to parameter of type 'Channel_row'.ts(2345)
Now, if I move or copy the get_row_by_id() and get_table_copy() functions into the subclass, the type errors go away. But I don't want to duplicate code unnecessarily.
How can I declare the functions in the parent class so it can be reused in child classes, but maintain the static type checking?
As a bonus, can I also generalize the clone() function so it doesn't need to be over-ridden in subclasses of db_row?

Product images are serving from different path in Frontend and Backend

Frontend Product images are serving from this path1 :
media/catalog/product/cache/1/image/9df78eab33525d08d6e5fb8d27136e95/i/m/img24.jpg
Backend Product images are serving from this path2
media/catalog/product/i/m/img24.jpg
why same images stored in different path.
I think Backend images are serving from proper path, I want frontend images also should serve from same path.
so we followed link & added following code in below file, but after that our site did't load any images.:
app/code/core/Mage/Catalog/Helper/Image.php
echo Mage::getModel('catalog/product_media_config')->getMediaUrl( $_product->getSmallImage());
full code :
<?php
class Mage_Catalog_Helper_Image extends Mage_Core_Helper_Abstract
{
/**
* Current model
*
* #var Mage_Catalog_Model_Product_Image
*/
protected $_model;
/**
* Scheduled for resize image
*
* #var bool
*/
protected $_scheduleResize = false;
/**
* Scheduled for rotate image
*
* #var bool
*/
protected $_scheduleRotate = false;
/**
* Angle
*
* #var int
*/
protected $_angle;
/**
* Watermark file name
*
* #var string
*/
protected $_watermark;
/**
* Watermark Position
*
* #var string
*/
protected $_watermarkPosition;
/**
* Watermark Size
*
* #var string
*/
protected $_watermarkSize;
/**
* Watermark Image opacity
*
* #var int
*/
protected $_watermarkImageOpacity;
/**
* Current Product
*
* #var Mage_Catalog_Model_Product
*/
protected $_product;
/**
* Image File
*
* #var string
*/
protected $_imageFile;
/**
* Image Placeholder
*
* #var string
*/
protected $_placeholder;
/**
* Reset all previous data
*
* #return Mage_Catalog_Helper_Image
*/
protected function _reset()
{
$this->_model = null;
$this->_scheduleResize = false;
$this->_scheduleRotate = false;
$this->_angle = null;
$this->_watermark = null;
$this->_watermarkPosition = null;
$this->_watermarkSize = null;
$this->_watermarkImageOpacity = null;
$this->_product = null;
$this->_imageFile = null;
return $this;
}
/**
* Initialize Helper to work with Image
*
* #param Mage_Catalog_Model_Product $product
* #param string $attributeName
* #param mixed $imageFile
* #return Mage_Catalog_Helper_Image
*/
public function init(Mage_Catalog_Model_Product $product, $attributeName, $imageFile=null)
{
$this->_reset();
$this->_setModel(Mage::getModel('catalog/product_image'));
$this->_getModel()->setDestinationSubdir($attributeName);
$this->setProduct($product);
$this->setWatermark(
Mage::getStoreConfig("design/watermark/{$this->_getModel()->getDestinationSubdir()}_image")
);
$this->setWatermarkImageOpacity(
Mage::getStoreConfig("design/watermark/{$this->_getModel()->getDestinationSubdir()}_imageOpacity")
);
$this->setWatermarkPosition(
Mage::getStoreConfig("design/watermark/{$this->_getModel()->getDestinationSubdir()}_position")
);
$this->setWatermarkSize(
Mage::getStoreConfig("design/watermark/{$this->_getModel()->getDestinationSubdir()}_size")
);
if ($imageFile) {
$this->setImageFile($imageFile);
} else {
// add for work original size
$this->_getModel()->setBaseFile($this->getProduct()->getData($this->_getModel()->getDestinationSubdir()));
}
return $this;
}
/**
* Schedule resize of the image
* $width *or* $height can be null - in this case, lacking dimension will be calculated.
*
* #see Mage_Catalog_Model_Product_Image
* #param int $width
* #param int $height
* #return Mage_Catalog_Helper_Image
*/
public function resize($width, $height = null)
{
$this->_getModel()->setWidth($width)->setHeight($height);
$this->_scheduleResize = true;
return $this;
}
/**
* Set image quality, values in percentage from 0 to 100
*
* #param int $quality
* #return Mage_Catalog_Helper_Image
*/
public function setQuality($quality)
{
$this->_getModel()->setQuality($quality);
return $this;
}
/**
* Guarantee, that image picture width/height will not be distorted.
* Applicable before calling resize()
* It is true by default.
*
* #see Mage_Catalog_Model_Product_Image
* #param bool $flag
* #return Mage_Catalog_Helper_Image
*/
public function keepAspectRatio($flag)
{
$this->_getModel()->setKeepAspectRatio($flag);
return $this;
}
/**
* Guarantee, that image will have dimensions, set in $width/$height
* Applicable before calling resize()
* Not applicable, if keepAspectRatio(false)
*
* $position - TODO, not used for now - picture position inside the frame.
*
* #see Mage_Catalog_Model_Product_Image
* #param bool $flag
* #param array $position
* #return Mage_Catalog_Helper_Image
*/
public function keepFrame($flag, $position = array('center', 'middle'))
{
$this->_getModel()->setKeepFrame($flag);
return $this;
}
/**
* Guarantee, that image will not lose transparency if any.
* Applicable before calling resize()
* It is true by default.
*
* $alphaOpacity - TODO, not used for now
*
* #see Mage_Catalog_Model_Product_Image
* #param bool $flag
* #param int $alphaOpacity
* #return Mage_Catalog_Helper_Image
*/
public function keepTransparency($flag, $alphaOpacity = null)
{
$this->_getModel()->setKeepTransparency($flag);
return $this;
}
/**
* Guarantee, that image picture will not be bigger, than it was.
* Applicable before calling resize()
* It is false by default
*
* #param bool $flag
* #return Mage_Catalog_Helper_Image
*/
public function constrainOnly($flag)
{
$this->_getModel()->setConstrainOnly($flag);
return $this;
}
/**
* Set color to fill image frame with.
* Applicable before calling resize()
* The keepTransparency(true) overrides this (if image has transparent color)
* It is white by default.
*
* #see Mage_Catalog_Model_Product_Image
* #param array $colorRGB
* #return Mage_Catalog_Helper_Image
*/
public function backgroundColor($colorRGB)
{
// assume that 3 params were given instead of array
if (!is_array($colorRGB)) {
$colorRGB = func_get_args();
}
$this->_getModel()->setBackgroundColor($colorRGB);
return $this;
}
/**
* Rotate image into specified angle
*
* #param int $angle
* #return Mage_Catalog_Helper_Image
*/
public function rotate($angle)
{
$this->setAngle($angle);
$this->_getModel()->setAngle($angle);
$this->_scheduleRotate = true;
return $this;
}
/**
* Add watermark to image
* size param in format 100x200
*
* #param string $fileName
* #param string $position
* #param string $size
* #param int $imageOpacity
* #return Mage_Catalog_Helper_Image
*/
public function watermark($fileName, $position, $size=null, $imageOpacity=null)
{
$this->setWatermark($fileName)
->setWatermarkPosition($position)
->setWatermarkSize($size)
->setWatermarkImageOpacity($imageOpacity);
return $this;
}
/**
* Set placeholder
*
* #param string $fileName
* #return void
*/
public function placeholder($fileName)
{
$this->_placeholder = $fileName;
}
/**
* Get Placeholder
*
* #return string
*/
public function getPlaceholder()
{
if (!$this->_placeholder) {
$attr = $this->_getModel()->getDestinationSubdir();
$this->_placeholder = 'images/catalog/product/placeholder/'.$attr.'.jpg';
}
return $this->_placeholder;
}
/**
* Return Image URL
*
* #return string
*/
public function __toString()
{
try {
$model = $this->_getModel();
if ($this->getImageFile()) {
$model->setBaseFile($this->getImageFile());
} else {
$model->setBaseFile($this->getProduct()->getData($model->getDestinationSubdir()));
}
if ($model->isCached()) {
return $model->getUrl();
} else {
if ($this->_scheduleRotate) {
$model->rotate($this->getAngle());
}
if ($this->_scheduleResize) {
$model->resize();
}
if ($this->getWatermark()) {
$model->setWatermark($this->getWatermark());
}
$url = $model->saveFile()->getUrl();
}
} catch (Exception $e) {
$url = Mage::getDesign()->getSkinUrl($this->getPlaceholder());
}
return $url;
}
/**
* Set current Image model
*
* #param Mage_Catalog_Model_Product_Image $model
* #return Mage_Catalog_Helper_Image
*/
protected function _setModel($model)
{
$this->_model = $model;
return $this;
}
/**
* Get current Image model
*
* #return Mage_Catalog_Model_Product_Image
*/
protected function _getModel()
{
return $this->_model;
}
/**
* Set Rotation Angle
*
* #param int $angle
* #return Mage_Catalog_Helper_Image
*/
protected function setAngle($angle)
{
$this->_angle = $angle;
return $this;
}
/**
* Get Rotation Angle
*
* #return int
*/
protected function getAngle()
{
return $this->_angle;
}
/**
* Set watermark file name
*
* #param string $watermark
* #return Mage_Catalog_Helper_Image
*/
protected function setWatermark($watermark)
{
$this->_watermark = $watermark;
$this->_getModel()->setWatermarkFile($watermark);
return $this;
}
/**
* Get watermark file name
*
* #return string
*/
protected function getWatermark()
{
return $this->_watermark;
}
/**
* Set watermark position
*
* #param string $position
* #return Mage_Catalog_Helper_Image
*/
protected function setWatermarkPosition($position)
{
$this->_watermarkPosition = $position;
$this->_getModel()->setWatermarkPosition($position);
return $this;
}
/**
* Get watermark position
*
* #return string
*/
protected function getWatermarkPosition()
{
return $this->_watermarkPosition;
}
/**
* Set watermark size
* param size in format 100x200
*
* #param string $size
* #return Mage_Catalog_Helper_Image
*/
public function setWatermarkSize($size)
{
$this->_watermarkSize = $size;
$this->_getModel()->setWatermarkSize($this->parseSize($size));
return $this;
}
/**
* Get watermark size
*
* #return string
*/
protected function getWatermarkSize()
{
return $this->_watermarkSize;
}
/**
* Set watermark image opacity
*
* #param int $imageOpacity
* #return Mage_Catalog_Helper_Image
*/
public function setWatermarkImageOpacity($imageOpacity)
{
$this->_watermarkImageOpacity = $imageOpacity;
$this->_getModel()->setWatermarkImageOpacity($imageOpacity);
return $this;
}
/**
* Get watermark image opacity
*
* #return int
*/
protected function getWatermarkImageOpacity()
{
if ($this->_watermarkImageOpacity) {
return $this->_watermarkImageOpacity;
}
return $this->_getModel()->getWatermarkImageOpacity();
}
/**
* Set current Product
*
* #param Mage_Catalog_Model_Product $product
* #return Mage_Catalog_Helper_Image
*/
protected function setProduct($product)
{
$this->_product = $product;
return $this;
}
/**
* Get current Product
*
* #return Mage_Catalog_Model_Product
*/
protected function getProduct()
{
return $this->_product;
}
/**
* Set Image file
*
* #param string $file
* #return Mage_Catalog_Helper_Image
*/
protected function setImageFile($file)
{
$this->_imageFile = $file;
return $this;
}
/**
* Get Image file
*
* #return string
*/
protected function getImageFile()
{
return $this->_imageFile;
}
/**
* Retrieve size from string
*
* #param string $string
* #return array|bool
*/
protected function parseSize($string)
{
$size = explode('x', strtolower($string));
if (sizeof($size) == 2) {
return array(
'width' => ($size[0] > 0) ? $size[0] : null,
'heigth' => ($size[1] > 0) ? $size[1] : null,
);
}
return false;
}
/**
* Retrieve original image width
*
* #return int|null
*/
public function getOriginalWidth()
{
return $this->_getModel()->getImageProcessor()->getOriginalWidth();
}
/**
* Retrieve original image height
*
* #deprecated
* #return int|null
*/
public function getOriginalHeigh()
{
return $this->getOriginalHeight();
}
/**
* Retrieve original image height
*
* #return int|null
*/
public function getOriginalHeight()
{
return $this->_getModel()->getImageProcessor()->getOriginalHeight();
}
/**
* Retrieve Original image size as array
* 0 - width, 1 - height
*
* #return array
*/
public function getOriginalSizeArray()
{
return array(
$this->getOriginalWidth(),
$this->getOriginalHeight()
);
}
/**
* Check - is this file an image
*
* #param string $filePath
* #return bool
* #throws Mage_Core_Exception
*/
public function validateUploadFile($filePath) {
if (!getimagesize($filePath)) {
Mage::throwException($this->__('Disallowed file type.'));
}
$_processor = new Varien_Image($filePath);
return $_processor->getMimeType() !== null;
}
echo Mage::getModel('catalog/product_media_config')->getMediaUrl( $_product->getSmallImage());
}
In frontend all product image come from cache due to increase speed.
In backend Magento not consider speed so it come from real image path.
You can not written any code out side of method because Magento is fully object oriented.
You can use below code for fetch image full url.
echo $imageUrl = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_MEDIA) . 'catalog/product' . $_product->getImage();

Using the onFrameAvailable() in Jacobi Google Tango API

Question: Does anyone know how to get the Tango's color camera image buffer using the Tango Java (Jacobi) API onFrameAvailable() callback?
Background:
I have an augmented reality application that displays video in the background of the Tango. I've successfully created the video overlay example using the the Java API (Jacobi) following this example. My application works fine, and the video is rendered in the background properly.
As part of the application, I'd like to store a copy of the video backbuffer when the user presses a button. Therefore, I need access to the camera's RGB data.
According to the Jacobi release notes, any class desiring access to the camera RGB data should implement the new onFrameAvailable() method in the OnTangoUpdateListener. I did this, but I don't see any handle or arguments to actually get the pixels:
Java API
#Override
public void onFrameAvailable(int cameraId) {
//Log.w(TAG, "Frame available!");
if (cameraId == TangoCameraIntrinsics.TANGO_CAMERA_COLOR) {
tangoCameraPreview.onFrameAvailable();
}
}
as shown, onFrameAvailable only has one argument, and integer designating the id of the camera generating the view. Contrast this with the C-library call back, which provides access to the image buffer:
C API
TangoErrorType TangoService_connectOnFrameAvailable(
TangoCameraId id, void* context,
void (*onFrameAvailable)(void* context, TangoCameraId id,
const TangoImageBuffer* buffer));
I was expecting the Java method to have something similar to the buffer object in the C API call.
What I've Tried
I tried extending the TangoCameraPreview class and saving the image there, but I only get a black background.
public class CameraSurfaceView extends TangoCameraPreview {
private boolean takeSnapShot = false;
public void takeSnapShot() {
takeSnapShot = true;
}
/**
* Grabs a copy of the surface (which is rendering the Tango color camera)
* https://stackoverflow.com/questions/14620055/how-to-take-a-screenshot-of-androids-surface-view
*/
public void screenGrab2(){
int width = this.getWidth();
int height = this.getHeight();
long fileprefix = System.currentTimeMillis();
View v= getRootView();
v.setDrawingCacheEnabled(true);
// this is the important code :)
// Without it the view will have a dimension of 0,0 and the bitmap will be null
v.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
v.layout(0, 0, width, height);
v.buildDrawingCache(true);
Bitmap image = v.getDrawingCache();
//TODO: make seperate subdirctories for each exploitation sessions
String targetPath =Environment.getExternalStorageDirectory() + "/RavenEye/Photos/";
String imageFileName = fileprefix + ".jpg";
if(!(new File(targetPath)).exists()) {
new File(targetPath).mkdirs();
}
try {
File targetDirectory = new File(targetPath);
File photo=new File(targetDirectory, imageFileName);
FileOutputStream fos=new FileOutputStream(photo.getPath());
image.compress(CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
Log.i(this.getClass().getCanonicalName(), "Grabbed an image in target path:" + targetPath);
} catch (FileNotFoundException e) {
Log.e(CameraPreview.class.getName(),"Exception " + e);
e.printStackTrace();
} catch (IOException e) {
Log.e(CameraPreview.class.getName(),"Exception " + e);
e.printStackTrace();
}
}
/**
* Grabs a copy of the surface (which is rendering the Tango color camera)
*/
public void screenGrab(){
int width = this.getWidth();
int height = this.getHeight();
long fileprefix = System.currentTimeMillis();
Bitmap image = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(image);
canvas.drawBitmap(image, 0, 0, null);
//TODO: make seperate subdirctories for each exploitation sessions
String targetPath =Environment.getExternalStorageDirectory() + "/RavenEye/Photos/";
String imageFileName = fileprefix + ".jpg";
if(!(new File(targetPath)).exists()) {
new File(targetPath).mkdirs();
}
try {
File targetDirectory = new File(targetPath);
File photo=new File(targetDirectory, imageFileName);
FileOutputStream fos=new FileOutputStream(photo.getPath());
image.compress(CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
Log.i(this.getClass().getCanonicalName(), "Grabbed an image in target path:" + targetPath);
} catch (FileNotFoundException e) {
Log.e(CameraPreview.class.getName(),"Exception " + e);
e.printStackTrace();
} catch (IOException e) {
Log.e(CameraPreview.class.getName(),"Exception " + e);
e.printStackTrace();
}
}
#Override
public void onFrameAvailable() {
super.onFrameAvailable();
if(takeSnapShot) {
screenGrab();
takeSnapShot = false;
}
}
public CameraSurfaceView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
}
Where I'm Heading
I'm preparing to root the device, and then using the onFrameAvailable method to cue an external root process such as one of these:
post 23610900
post 10965409
post 4998527
I'm hoping I can find a way to avoid the root hack.
Thank you in advance!
OK, I figured out a way to make it work.
Update: My working solution is here:
https://github.com/stevehenderson/GoogleTango_AR_VideoCapture
I essentially set up a "man (renderer) in the middle" attack on the rendering pipeline.
This approach intercepts the SetRenderer call from the TangoCameraPreview base class, and allows one to get access
to the base renderer's OnDraw() method and the GL context. I then add additional methods to this extended renderer that allow reading of the GL buffer.
General approach
1) Extend the TangoCameraPreview class (e.g. in my example ReadableTangoCameraPreview). Override the setRenderer(GLSurfaceView.Renderer renderer), keeping a reference to the base renderer, and replacing the renderer with your own "wrapped" GLSUrface.Renderer renderer that will add methods to render the backbuffer to an image on the device.
2) Create your own GLSurfaceView.Renderer Interface (e.g. my ScreenGrabRenderer class ) that implements all the GLSurfaceView.Renderer methods, passing them on to the base renderer captured in Step 1. Also, add a few new methods to "cue" when you want to grab the image.
3) Implement the ScreenGrabRenderer described in step 2 above.
4) Use a callback interface (my TangoCameraScreengrabCallback) to communicate when an image has been copied
It works pretty well, and allows one to grab the camera bits in an image without rooting the device.
Note: I haven't had the need to closely synchronize my captured images with the point cloud. So I haven't checked the latency. For best results, you may need to invoke the C methods proposed by Mark.
Here's what each of my classes looks like..
///Main Activity Class where bulk of Tango code is
.
.
.
// Create our Preview view and set it as the content of our activity.
mTangoCameraPreview = new ReadableTangoCameraPreview(getActivity());
RelativeLayout preview = (RelativeLayout) view.findViewById(R.id.camera_preview);
preview.addView(mTangoCameraPreview);
.
.
.
//When you want to take a snapshot, call the takeSnapShotMethod()
//(you can make this respond to a button)
mTangoCameraPreview.takeSnapShot();
.
.
.
.
.
//Main Tango Listeners
#Override
public void onFrameAvailable(final int cameraId) {
// Update the UI with TangoPose information
runOnUiThread(new Runnable() {
#Override
public void run() {
if (cameraId == TangoCameraIntrinsics.TANGO_CAMERA_COLOR) {
tangoCameraPreview.onFrameAvailable();
}
}
});
}
ReadableTangoCameraPreview Class
public class ReadableTangoCameraPreview extends TangoCameraPreview implements TangoCameraScreengrabCallback {
Activity mainActivity;
private static final String TAG = ReadableTangoCameraPreview.class.getSimpleName();
//An intercept renderer
ScreenGrabRenderer screenGrabRenderer;
private boolean takeSnapShot = false;
#Override
public void setRenderer(GLSurfaceView.Renderer renderer) {
//Create our "man in the middle"
screenGrabRenderer= new ScreenGrabRenderer(renderer);
//Set it's call back
screenGrabRenderer.setTangoCameraScreengrabCallback(this);
//Tell the TangoCameraPreview class to use this intermediate renderer
super.setRenderer(screenGrabRenderer);
Log.i(TAG,"Intercepted the renderer!!!");
}
/**
* Set a trigger for snapshot. Call this from main activity
* in response to a use input
*/
public void takeSnapShot() {
takeSnapShot = true;
}
#Override
public void onFrameAvailable() {
super.onFrameAvailable();
if(takeSnapShot) {
//screenGrabWithRoot();
screenGrabRenderer.grabNextScreen(0,0,this.getWidth(),this.getHeight());
takeSnapShot = false;
}
}
public ReadableTangoCameraPreview(Activity context) {
super(context);
mainActivity = context;
}
public void newPhoto(String aNewPhotoPath) {
//This gets called when a new photo was grabbed created in the renderer
Log.i(TAG,"New image available at" + aNewPhotoPath);
}
}
ScreenGrabRenderer Interface
(Overloads the TangoCameraPreview default Renderer)
/**
* This is an intermediate class that intercepts all calls to the TangoCameraPreview's
* default renderer.
*
* It simply passes all render calls through to the default renderer.
*
* When required, it can also use the renderer methods to dump a copy of the frame to a bitmap
*
* #author henderso
*
*/
public class ScreenGrabRenderer implements GLSurfaceView.Renderer {
TangoCameraScreengrabCallback mTangoCameraScreengrabCallback;
GLSurfaceView.Renderer tangoCameraRenderer;
private static final String TAG = ScreenGrabRenderer.class.getSimpleName();
private String lastFileName = "unset";
boolean grabNextScreen = false;
int grabX = 0;
int grabY = 0;
int grabWidth = 640;
int grabHeight = 320;
public void setTangoCameraScreengrabCallback(TangoCameraScreengrabCallback aTangoCameraScreengrabCallback) {
mTangoCameraScreengrabCallback = aTangoCameraScreengrabCallback;
}
/**
* Cue the renderer to grab the next screen. This is a signal that will
* be detected inside the onDrawFrame() method
*
* #param b
*/
public void grabNextScreen(int x, int y, int w, int h) {
grabNextScreen = true;
grabX=x;
grabY=y;
grabWidth=w;
grabHeight=h;
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
tangoCameraRenderer.onSurfaceCreated(gl, config);
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
tangoCameraRenderer.onSurfaceChanged(gl, width, height);
}
#Override
public void onDrawFrame(GL10 gl) {
tangoCameraRenderer.onDrawFrame(gl);
if(grabNextScreen) {
screenGrab(gl);
grabNextScreen=false;
}
}
/**
*
* Creates a bitmap given a certain dimension and an OpenGL context
*
* This code was lifted from here:
*
* http://stackoverflow.com/questions/5514149/capture-screen-of-glsurfaceview-to-bitmap
*/
private Bitmap createBitmapFromGLSurface(int x, int y, int w, int h, GL10 gl)
throws OutOfMemoryError {
int bitmapBuffer[] = new int[w * h];
int bitmapSource[] = new int[w * h];
IntBuffer intBuffer = IntBuffer.wrap(bitmapBuffer);
intBuffer.position(0);
try {
gl.glReadPixels(x, y, w, h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, intBuffer);
int offset1, offset2;
for (int i = 0; i < h; i++) {
offset1 = i * w;
offset2 = (h - i - 1) * w;
for (int j = 0; j < w; j++) {
int texturePixel = bitmapBuffer[offset1 + j];
int blue = (texturePixel >> 16) & 0xff;
int red = (texturePixel << 16) & 0x00ff0000;
int pixel = (texturePixel & 0xff00ff00) | red | blue;
bitmapSource[offset2 + j] = pixel;
}
}
} catch (GLException e) {
Log.e(TAG,e.toString());
return null;
}
return Bitmap.createBitmap(bitmapSource, w, h, Bitmap.Config.ARGB_8888);
}
/**
* Writes a copy of the GLSurface backbuffer to storage
*/
private void screenGrab(GL10 gl) {
long fileprefix = System.currentTimeMillis();
String targetPath =Environment.getExternalStorageDirectory() + "/RavenEye/Photos/";
String imageFileName = fileprefix + ".png";
String fullPath = "error";
Bitmap image = createBitmapFromGLSurface(grabX,grabY,grabWidth,grabHeight,gl);
if(!(new File(targetPath)).exists()) {
new File(targetPath).mkdirs();
}
try {
File targetDirectory = new File(targetPath);
File photo=new File(targetDirectory, imageFileName);
FileOutputStream fos=new FileOutputStream(photo.getPath());
image.compress(CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
fullPath =targetPath + imageFileName;
Log.i(TAG, "Grabbed an image in target path:" + fullPath);
///Notify the outer class(es)
if(mTangoCameraScreengrabCallback != null) {
mTangoCameraScreengrabCallback.newPhoto(fullPath);
} else {
Log.i(TAG, "Callback not set properly..");
}
} catch (FileNotFoundException e) {
Log.e(TAG,"Exception " + e);
e.printStackTrace();
} catch (IOException e) {
Log.e(TAG,"Exception " + e);
e.printStackTrace();
}
lastFileName = fullPath;
}
/**
* Constructor
* #param baseRenderer
*/
public ScreenGrabRenderer(GLSurfaceView.Renderer baseRenderer) {
tangoCameraRenderer = baseRenderer;
}
}
TangoCameraScreengrabCallback Interface
(not required unless you want to pass info back from the screen grab renderer)
/*
* The TangoCameraScreengrabCallback is a generic interface that provides callback mechanism
* to an implementing activity.
*
*/
interface TangoCameraScreengrabCallback {
public void newPhoto(String aNewPhotoPath);
}
I haven't tried on the latest release, but it was the absence of this functionality that drove me to the C API where I could get image data - a recent post, I think on the G+ page, seemed to indicate that the Unity API now returns image data as well - for a company that wants to keep scolding us when we don't use Java, it certainly is an odd lag :-)

Why isn't my RCP application splash showing in Windows?

I've created an RCP application with an interactive splash for logging onto my system. I built it on a Mac, and the application works perfectly, but when I created a new product configuration for Windows and run the application, it launches without the splash and there are no errors appearing in the console.
The splash handler code is as follows
/**
* The splash screen controller for the RCP application. This has been modified to also act as a login screen for the
* application. Failure to correctly authenticate results in the application termination.
*/
package com.myproject.plugins.core.splashHandlers;
import java.net.MalformedURLException;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.splash.AbstractSplashHandler;
/**
* The splash handler overrides the default RCP splash handler.
* #since 3.3
*/
public class InteractiveSplashHandler extends AbstractSplashHandler {
/**
* Composite container for login form.
*/
private Composite loginComposite;
/**
* Text box input for login username.
*/
private Text usernameTextBox;
/**
* Text box input for login password.
*/
private Text passwordTextBox;
/**
* OK button for submission of the login form.
*/
private Button okButton;
/**
* Cancel button for cancelling the login attempt and exiting the application.
*/
private Button cancelButton;
/**
* Simple boolean flag to store login success/status.
*/
private boolean isAuthenticated;
/**
* SWT form label for username.
*/
private Label usernameLabel;
/**
* SWT form label for password.
*/
private Label passwordLabel;
/**
* Form/layout data for username label.
*/
private FormData usernameLabelFormData;
/**
* Form/layout data for password label.
*/
private FormData passwordLabelFormData;
/**
* Form/layout data for username text box.
*/
private FormData usernameTextBoxFormData;
/**
* Form/layout data for password text box.
*/
private FormData passwordTextBoxFormData;
/**
* Form/layout data for OK button.
*/
private FormData okButtonFormData;
/**
* Constructor for the splash handler.
*/
public InteractiveSplashHandler() {
passwordTextBox = null;
cancelButton = null;
isAuthenticated = false;
}
/**
* Initialiser for the splash screen.
* #see org.eclipse.ui.splash.AbstractSplashHandler#init(org.eclipse.swt.widgets.Shell)
*/
public void init(final Shell splash) {
/**
* Initialising the parent SplashHandler with the splash shell.
*/
super.init(splash);
/**
* Configure the shell UI layout.
*/
configureUISplash();
/**
* Create UI components.
*/
createUI();
/**
* Create UI listeners.
*/
createUIListeners();
/**
* Force the splash screen to layout.
*/
splash.layout(true);
/**
* Keep the splash screen visible and prevent the RCP application from loading until the close button is
* clicked.
*/
doEventLoop();
}
/**
* Create the event loop for the splash to prevent the application load from completion, and hold it at the splash
* until the login event is successful.
*/
private void doEventLoop() {
Shell splash = getSplash();
while (isAuthenticated == false) {
if (splash.getDisplay().readAndDispatch() == false) {
splash.getDisplay().sleep();
}
}
}
/**
* Create the UI listeners for all the form components.
*/
private void createUIListeners() {
/**
* Create the OK button listeners.
*/
createUIListenersButtonOK();
/**
* Create the cancel button listeners.
*/
createUIListenersButtonCancel();
}
/**
* Listeners setup for the cancel button.
*/
private void createUIListenersButtonCancel() {
cancelButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
handleButtonCancelWidgetSelected();
}
});
}
/**
* Handles the cancel action by shutting down the RCP application.
*/
private void handleButtonCancelWidgetSelected() {
/**
* Abort the loading of the RCP application.
*/
getSplash().getDisplay().close();
System.exit(0);
}
/**
* Listeners setup for the OK button.
*/
private void createUIListenersButtonOK() {
okButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
handleButtonOKWidgetSelected();
}
});
}
/**
* Handles the OK button being pressed and the login attempted.
*/
private void handleButtonOKWidgetSelected() {
String username = usernameTextBox.getText();
String password = passwordTextBox.getText();
AuthenticationClient client = new AuthenticationClient();
if (username.equals("") || password.equals("")) {
MessageDialog.openError(getSplash(),
"Authentication Failed", //$NON-NLS-1$
"A username and password must be specified to login."); //$NON-NLS-1$
} else {
try {
if (client.authenticate(username, password)) {
isAuthenticated = true;
} else {
MessageDialog.openError(getSplash(),
"Authentication Failed", //$NON-NLS-1$
"The details you entered could not be verified."); //$NON-NLS-1$
}
} catch (MalformedURLException e) {
MessageDialog.openError(getSplash(),
"Authentication Failed", //$NON-NLS-1$
"Service responded with an error."); //$NON-NLS-1$
}
}
}
/**
* Calls the individual UI component creation functions.
*/
private void createUI() {
/**
* Create the login panel.
*/
createUICompositeLogin();
/**
* Create the user name label.
*/
createUILabelUserName();
/**
* Create the user name text widget.
*/
createUITextUserName();
/**
* Create the password label.
*/
createUILabelPassword();
/**
* Create the password text widget.
*/
createUITextPassword();
/**
* Create the OK button.
*/
createUIButtonOK();
/**
* Create the cancel button.
*/
createUIButtonCancel();
}
/**
* Creates the SWT component for the cancel button.
*/
private void createUIButtonCancel() {
/**
* Create the button.
*/
cancelButton = new Button(loginComposite, SWT.PUSH);
okButtonFormData.right = new FormAttachment(cancelButton, -6);
FormData cancelButtonFormData = new FormData();
cancelButtonFormData.left = new FormAttachment(0, 392);
cancelButtonFormData.right = new FormAttachment(100, -10);
cancelButtonFormData.bottom = new FormAttachment(100, -10);
cancelButton.setLayoutData(cancelButtonFormData);
cancelButton.setText("Cancel");
}
/**
* Creates the SWT component for the OK button.
*/
private void createUIButtonOK() {
/**
* Create the button.
*/
okButton = new Button(loginComposite, SWT.PUSH);
passwordTextBoxFormData.bottom = new FormAttachment(okButton, -6);
okButtonFormData = new FormData();
okButtonFormData.left = new FormAttachment(0, 279);
okButtonFormData.bottom = new FormAttachment(100, -10);
okButton.setLayoutData(okButtonFormData);
okButton.setText("OK");
}
/**
* Creates the SWT component for the password text box.
*/
private void createUITextPassword() {
/**
* Create the text widget.
*/
int style = SWT.PASSWORD | SWT.BORDER;
passwordTextBox = new Text(loginComposite, style);
passwordLabelFormData.right = new FormAttachment(passwordTextBox, -6);
passwordTextBoxFormData = new FormData();
passwordTextBoxFormData.right = new FormAttachment(100, -10);
passwordTextBoxFormData.left = new FormAttachment(0, 279);
passwordTextBox.setLayoutData(passwordTextBoxFormData);
}
/**
* Creates the SWT component for the password label.
*/
private void createUILabelPassword() {
/**
* Create the label.
*/
passwordLabel = new Label(loginComposite, SWT.NONE);
passwordLabelFormData = new FormData();
passwordLabelFormData.top = new FormAttachment(usernameLabel, 11);
passwordLabel.setLayoutData(passwordLabelFormData);
passwordLabel.setText("&Password:");
}
/**
* Creates SWT component for the username text box.
*/
private void createUITextUserName() {
/**
* Create the text widget.
*/
usernameTextBox = new Text(loginComposite, SWT.BORDER);
usernameLabelFormData.top = new FormAttachment(usernameTextBox, 3, SWT.TOP);
usernameLabelFormData.right = new FormAttachment(usernameTextBox, -6);
usernameTextBoxFormData = new FormData();
usernameTextBoxFormData.top = new FormAttachment(0, 233);
usernameTextBoxFormData.right = new FormAttachment(100, -10);
usernameTextBoxFormData.left = new FormAttachment(0, 279);
usernameTextBox.setLayoutData(usernameTextBoxFormData);
}
/**
* Creates SWT component for the username label.
*/
private void createUILabelUserName() {
/**
* Create the label
*/
usernameLabel = new Label(loginComposite, SWT.NONE);
usernameLabelFormData = new FormData();
usernameLabel.setLayoutData(usernameLabelFormData);
usernameLabel.setText("&User Name:");
}
/**
* Creates SWT component for the login composite.
*/
private void createUICompositeLogin() {
/**
* Create the composite and set the layout.
*/
loginComposite = new Composite(getSplash(), SWT.BORDER);
loginComposite.setLayout(new FormLayout());
}
/**
* Configures the splash screen SWT/UI components.
*/
private void configureUISplash() {
/**
* Configure layout
*/
FillLayout layout = new FillLayout();
getSplash().setLayout(layout);
/**
* Force shell to inherit the splash background
*/
getSplash().setBackgroundMode(SWT.INHERIT_DEFAULT);
}
}
Oddly enough, the bitmap (created in Photoshop/Mac) image was seen as corrupt in Eclipse, but opened fine in all graphics applications (including Photoshop/Win). I opened the file in MS Paint and saved without changes. The splash started working fine.
Check your bitmap if you get this error!

I have a modal Window implemented in SmartGWT - how can I close it when someone clicks off of the window?

I've created a class that extends the Window SmartGWT class, and it is set to be modal. I am trying to make the Window close when a user clicks off the window. I have tried to link it up to a FocusChangedHandler with no luck. Has anyone done something like this before?
/**
* Sets up a modal Dialog box that lets the user edit attributes associated
* with the properties of the {#link LabElement} that are given.
*
* #author Therin Irwin
*/
public class EditorDialog extends Window {
final DynamicForm dyn = new DynamicForm();
final RichTextEditor richTextEditor = new RichTextEditor();
final List attrItems = new ArrayList();
/**
* Creates a new EditorDialog with a RichTextEditor and a list of
* attributes for the element.
*
* #param name the name of the element being edited.
* #param attr the List of String attributes of the element that can be
* edited.
* #param hasText true if the element supports text inside, false if not.
*/
public EditorDialog(String name, List attr, boolean hasText) {
super();
VLayout vert = new VLayout();
this.setShowMinimizeButton(false);
this.setIsModal(true);
this.setShowModalMask(true);
this.setTitle(name + " Editor");
richTextEditor.setWidth(550);
richTextEditor.setHeight(100);
richTextEditor.setPadding(5);
richTextEditor.setCanDragResize(true);
richTextEditor.setResizeFrom("B");
richTextEditor.setShowEdges(true);
if (attr == null || attr.size() == 0) {
richTextEditor.setHeight(300);
}
else {
int i = 0;
FormItem[] fi = new FormItem[attr.size()];
for (String at : attr) {
TextItem temp = new TextItem(at, at);
attrItems.add(temp);
fi[i++] = temp;
}
dyn.setFields(fi);
dyn.setPadding(5);
dyn.setTop(100);
}
if (hasText)
vert.addMember(richTextEditor);
if (!(attr == null || attr.size() == 0))
vert.addMember(dyn);
this.addItem(vert);
this.centerInPage();
this.setAutoSize(true);
}
/**
* Returns the text of the RichTextEditor.
*
* #return the text entered into the RichTextEditor.
*/
public String getRichText() {
return richTextEditor.getValue();
}
/**
* Sets the text in the RichTextEditor to String value.
*
* #param value the String to put as the contents of the RichTextEditor.
*/
public void setRichText(String value) {
richTextEditor.setValue(value);
}
/**
* Returns the List of TextItems that hold the user-entered values for
* attributes.
*
* #return the TextItems associated with each attribute, in order.
*/
public DynamicForm getFormItems() {
return dyn;
}
public TextItem getFormItem(int item) {
return (TextItem) dyn.getFields()[item];
}
}
#Therin
I guess according to your requirement, you need to implement this property of Window:
this.setDismissOnOutsideClick(true);

Resources