I am trying to create a small application which displays an Image that you selected in a File chooser. It should then resize when the user resizes the window.
My app works up to the point where I add this code to the constructor of my class which should give the image the ability to resize when the window is resized.
window.size_allocate.connect(() => {
resize_image(); //<-- a problem
});
this "should" call the method resize_image when the window changes its size but everytime I add this code, my virtual machine on which I run elementary os crashes and stops working ( I have to restart everytime I try to run my program).
the method resize_image() works as following:
public void resize_image()
{
try
{ if(buf.get_width() < window.get_allocated_width()){
buf = buf.scale_simple(window.get_allocated_width(), window.get_allocated_width(), Gdk.InterpType.NEAREST);
image.set_from_pixbuf(buf);
}
}catch(Error e)
{
}
}
(I know that my resizing "alogrithm" isnt the best yet but I just used this method for testing.)
Now my question:
Why is my program crashing? Is the conversion from pixbuf to image too slow for the user?
Is there another way to resize the image to the window size?
Any help would be appreciated :)
The trick here is to add a layout and set the resize callback not to the window but to the layout. It's not perfect, it's a bit dirty but works. Initial positioning not working good but there's rooms to improvement.
Must check Gtk.Widget and Gtk.Containers for requested, allocated and natural sizes or even use Gdk methods. Getting late, hope this will lead you in the right direction.
PS: I'm using a endless.png image but feel free to use another one, just change the code to reflect it.
using Gtk;
public int main (string[] args) {
Gtk.Image image;
Gtk.Layout layout;
Gtk.Window window;
Gdk.Pixbuf pixbuf;
Gtk.init (ref args);
window = new Gtk.Window ();
layout = new Gtk.Layout ();
image = new Gtk.Image ();
try {
pixbuf = new Gdk.Pixbuf.from_file ("endless.png");
image = new Gtk.Image.from_pixbuf (pixbuf);
layout.put (image, 0,0);
window.add (layout);
layout.size_allocate.connect ((allocation) => {
print ("Width: %d Height: %d\n", allocation.width, allocation.height);
var pxb = pixbuf.scale_simple (allocation.width, allocation.height, Gdk.InterpType.BILINEAR);
image.set_from_pixbuf (pxb);
});
window.destroy.connect (Gtk.main_quit);
window.show_all ();
Gtk.main ();
return 0;
} catch (Error e) {
stderr.printf ("Could not load file...exit (%s)\n", e.message);
return 1;
}
}
EDIT:
A simple cairo version:
using Gtk;
using Cairo;
public int main (string[] args) {
Cairo.ImageSurface image;
image = new Cairo.ImageSurface.from_png ("endless.png");
Gtk.init (ref args);
var window = new Gtk.Window ();
var darea = new DrawingArea ();
window.add (darea);
window.show_all ();
darea.draw.connect ((cr) => {
float xscale;
float yscale;
cr.save ();
xscale = (float) darea.get_allocated_width () / image.get_width ();
yscale = (float) darea.get_allocated_height () / image.get_height ();
cr.scale (xscale, yscale);
cr.set_source_surface (image, 0, 0);
cr.paint ();
cr.restore ();
return true;
});
window.destroy.connect (Gtk.main_quit);
Gtk.main ();
return 0;
}
EDIT 2:
I've created another version to toggle between 2 images and check if while doing this quite a few times and check if the memory increases, but it does not. Added a couple of Boxes, and added 2 buttons.
using Gtk;
using Cairo;
public int main (string[] args) {
Cairo.ImageSurface image;
image = new Cairo.ImageSurface.from_png ("endless.png");
Gtk.init (ref args);
var window = new Gtk.Window ();
var box1 = new Gtk.Box (Gtk.Orientation.VERTICAL, 0);
var box2 = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0);
var b1 = new Gtk.Button.with_label ("Image1");
var b2 = new Gtk.Button.with_label ("Image2");
box2.pack_start (b1, true, true, 0);
box2.pack_end (b2, true, true, 0);
var darea = new DrawingArea ();
box1.pack_start (box2, false, false, 0);
box1.pack_end (darea, true, true, 0);
window.add (box1);
window.show_all ();
b1.clicked.connect (() => {
image = new Cairo.ImageSurface.from_png ("endless.png");
darea.queue_draw ();
});
b2.clicked.connect (() => {
image = new Cairo.ImageSurface.from_png ("Gnome-logo.png");
darea.queue_draw ();
});
darea.draw.connect ((cr) => {
float xscale;
float yscale;
cr.save ();
xscale = (float) darea.get_allocated_width () / image.get_width ();
yscale = (float) darea.get_allocated_height () / image.get_height ();
cr.scale (xscale, yscale);
cr.set_source_surface (image, 0, 0);
cr.paint ();
cr.restore ();
return true;
});
window.destroy.connect (Gtk.main_quit);
Gtk.main ();
return 0;
}
Related
I am have a bit of a problem converting some color PDFs to tiff images. The PDFs I am having problems with have hand written signatures written in blue ink. These signatures do not appear in the generated binary tiffs. I suspect there is a threshold value somewhere to determine which pixels will be black and which will be white.
#SuppressWarnings("serial")
private static void convertPdfToTiff(final File pdf, final File tif) throws Exception {
try
{
final Iterator<ImageWriter> imageWriterIterator = ImageIO.getImageWritersByFormatName("TIF");
final ImageWriter imageWriter = imageWriterIterator.hasNext() ? imageWriterIterator.next() : null;
final TIFFImageWriteParam writeParam = new TIFFImageWriteParam(Locale.getDefault());
writeParam.setCompressionMode(TIFFImageWriteParam.MODE_EXPLICIT);
writeParam.setCompressionType("LZW");
PDDocument pdfDocument = PDDocument.load(pdf);
PDFRenderer pdfRenderer = new PDFRenderer(pdfDocument);
OutputStream out = new FileOutputStream(tif);
final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(out);
final ImageOutputStream imageOutputStream = ImageIO.createImageOutputStream(bufferedOutputStream);
imageWriter.setOutput(imageOutputStream);
imageWriter.prepareWriteSequence(null);
int pageCounter = 0;
for (PDPage page : pdfDocument.getPages())
{
BufferedImage image = pdfRenderer.renderImageWithDPI(pageCounter, 300, ImageType.BINARY);
final IIOImage s = new IIOImage(image, null, new TIFFImageMetadata(new TIFFIFD(new Vector<BaselineTIFFTagSet>()
{
{
add(BaselineTIFFTagSet.getInstance());
}
})))
{
{
final TIFFImageMetadata tiffMetadata = (TIFFImageMetadata) getMetadata();
final TIFFIFD rootIFD = tiffMetadata.getRootIFD();
final BaselineTIFFTagSet base = BaselineTIFFTagSet.getInstance();
rootIFD.addTIFFField(new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_X_RESOLUTION), TIFFTag.TIFF_RATIONAL, 1, new long[][] { { 300, 1 } }));
rootIFD.addTIFFField(new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_Y_RESOLUTION), TIFFTag.TIFF_RATIONAL, 1, new long[][] { { 300, 1 } }));
}
};
imageWriter.writeToSequence(s, writeParam);
pageCounter++;
}
imageWriter.dispose();
imageOutputStream.flush();
imageOutputStream.close();
bufferedOutputStream.flush();
bufferedOutputStream.close();
pdfDocument.close();
out.flush();
out.close();
}
catch (Exception e)
{
e.printStackTrace();
throw e;
}
}
I had the same problem (blue signatures) some time ago and I did this:
render to RGB
convert to b/w with a filter from JH Labs (I got pointed to this by a comment in this answer)
I initially tried the dither and the diffusion filter
the filter that worked best for me was the bias part (I think I used 0.3) of the gain filter combined with the diffusion filter.
you can combine two filters with the compound filter.
the jhlabs stuff is not available as .jar file, but you can download the sources and add it to your project
some examples
Btw, save your files not as LZW, but as G4, that'll make them smaller. PDFBox has methods to efficiently save into images, see here. ImageIOUtil.writeImage() will save to G4 compressed TIFF if your BufferedImage is of type BITONAL.
I ended up rendering the image as grayscale and re drawing it to a second bw image.
#SuppressWarnings("serial")
private static void convertPdfToTiff(final File pdf, final File tif) throws Exception {
try
{
final Iterator<ImageWriter> imageWriterIterator = ImageIO.getImageWritersByFormatName("TIF");
final ImageWriter imageWriter = imageWriterIterator.hasNext() ? imageWriterIterator.next() : null;
final TIFFImageWriteParam writeParam = new TIFFImageWriteParam(Locale.getDefault());
writeParam.setCompressionMode(TIFFImageWriteParam.MODE_EXPLICIT);
writeParam.setCompressionType("CCITT T.6");
PDDocument pdfDocument = PDDocument.load(pdf);
PDFRenderer pdfRenderer = new PDFRenderer(pdfDocument);
OutputStream out = new FileOutputStream(tif);
final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(out);
final ImageOutputStream imageOutputStream = ImageIO.createImageOutputStream(bufferedOutputStream);
imageWriter.setOutput(imageOutputStream);
imageWriter.prepareWriteSequence(null);
int pageCounter = 0;
for (PDPage page : pdfDocument.getPages())
{
BufferedImage image = pdfRenderer.renderImageWithDPI(pageCounter, 300, ImageType.GRAY);
BufferedImage image2 = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_BINARY);
Graphics2D g = image2.createGraphics();
g.drawRenderedImage(image, null);
g.dispose();
final IIOImage s = new IIOImage(image2, null, new TIFFImageMetadata(new TIFFIFD(new Vector<BaselineTIFFTagSet>()
{
{
add(BaselineTIFFTagSet.getInstance());
}
})))
{
{
final TIFFImageMetadata tiffMetadata = (TIFFImageMetadata) getMetadata();
final TIFFIFD rootIFD = tiffMetadata.getRootIFD();
final BaselineTIFFTagSet base = BaselineTIFFTagSet.getInstance();
rootIFD.addTIFFField(new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_X_RESOLUTION), TIFFTag.TIFF_RATIONAL, 1, new long[][] { { 300, 1 } }));
rootIFD.addTIFFField(new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_Y_RESOLUTION), TIFFTag.TIFF_RATIONAL, 1, new long[][] { { 300, 1 } }));
}
};
imageWriter.writeToSequence(s, writeParam);
pageCounter++;
}
imageWriter.dispose();
imageOutputStream.flush();
imageOutputStream.close();
bufferedOutputStream.flush();
bufferedOutputStream.close();
pdfDocument.close();
out.flush();
out.close();
}
catch (Exception e)
{
e.printStackTrace();
throw e;
}
}
Anyone can help in this code, the pdf file is not loading in app and just showing blank white screen, Logcat showing FileNotFoundExeeption: /storage/sdcard/raw/ourpdf.pdf.
i am trying to make an app that will show information while i click buttons and every button will be active for specific pdf file reading. Any specific help please.
Thanks for help
part1
package com.code.androidpdf;
public class MainActivity extends Activity {
//Globals:
private WebView wv;
private int ViewSize = 0;
//OnCreate Method:
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Settings
PDFImage.sShowImages = true; // show images
PDFPaint.s_doAntiAlias = true; // make text smooth
HardReference.sKeepCaches = true; // save images in cache
//Setup above
wv = (WebView)findViewById(R.id.webView1);
wv.getSettings().setBuiltInZoomControls(true);//show zoom buttons
wv.getSettings().setSupportZoom(true);//allow zoom
//get the width of the webview
wv.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener()
{
#Override
public void onGlobalLayout()
{
ViewSize = wv.getWidth();
wv.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
pdfLoadImages();//load images
}
private void pdfLoadImages() {
try
{
// run async
new AsyncTask<Void, Void, Void>()
{
// create and show a progress dialog
ProgressDialog progressDialog = ProgressDialog.show(MainActivity.this, "", "Opening...");
#Override
protected void onPostExecute(Void result)
{
//after async close progress dialog
progressDialog.dismiss();
}
#Override
protected Void doInBackground(Void... params)
{
try
{
// select a document and get bytes
File file = new File(Environment.getExternalStorageDirectory().getPath()+"/randompdf.pdf");
RandomAccessFile raf = new RandomAccessFile(file, "r");
FileChannel channel = raf.getChannel();
net.sf.andpdf.nio.ByteBuffer bb = null ;
raf.close();
// create a pdf doc
PDFFile pdf = new PDFFile(bb);
//Get the first page from the pdf doc
PDFPage PDFpage = pdf.getPage(1, true);
//create a scaling value according to the WebView Width
final float scale = ViewSize / PDFpage.getWidth() * 0.95f;
//convert the page into a bitmap with a scaling value
Bitmap page = PDFpage.getImage((int)(PDFpage.getWidth() * scale), (int)(PDFpage.getHeight() * scale), null, true, true);
//save the bitmap to a byte array
ByteArrayOutputStream stream = new ByteArrayOutputStream();
page.compress(Bitmap.CompressFormat.PNG, 100, stream);
stream.close();
byte[] byteArray = stream.toByteArray();
//convert the byte array to a base64 string
String base64 = Base64.encodeToString(byteArray, Base64.DEFAULT);
//create the html + add the first image to the html
String html = "<!DOCTYPE html><html><body bgcolor=\"#7f7f7f\"><img src=\"data:image/png;base64,"+base64+"\" hspace=10 vspace=10><br>";
//loop through the rest of the pages and repeat the above
for(int i = 2; i <= pdf.getNumPages(); i++)
{
PDFpage = pdf.getPage(i, true);
page = PDFpage.getImage((int)(PDFpage.getWidth() * scale), (int)(PDFpage.getHeight() * scale), null, true, true);
stream = new ByteArrayOutputStream();
page.compress(Bitmap.CompressFormat.PNG, 100, stream);
stream.close();
byteArray = stream.toByteArray();
base64 = Base64.encodeToString(byteArray, Base64.DEFAULT);
html += "<img src=\"data:image/png;base64,"+base64+"\" hspace=10 vspace=10><br>";
}
html += "</body></html>";
//load the html in the webview
wv.loadDataWithBaseURL("", html, "text/html","UTF-8", "");
}
catch (Exception e)
{
Log.d("CounterA", e.toString());
}
return null;
}
}.execute();
System.gc();// run GC
}
catch (Exception e)
{
Log.d("error", e.toString());
}
}
}
It is (sadly) not possible to view a PDF that is stored locally in your devices. Android L has introduced the feature. So, to display a PDF , you have two options:
See this answer for using webview
How to open local pdf file in webview in android? (note that this requires an internet connection)
Use a third party pdf Viewer.
You can also send an intent for other apps to handle your pdf.
You can get an InputStream for the file using
getResources().openRawResource(R.raw.ourpdf)
Docs: http://developer.android.com/reference/android/content/res/Resources.html#openRawResource(int)
I'm trying to switch a banner adView to imageView just before I take a screenshot so that users can share this screenshot through share intent.
However, when I take the screenshot, it does not include the imageView.
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
....
adView1 = new AdView(this, AdSize.BANNER, MY_AD_UNIT_ID1);
LinearLayout.LayoutParams childParam2 = new
LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0, 0.10f);
adView1.setLayoutParams(childParam2);
adView1.loadAd(new AdRequest());
ll.addView(adView1);
setContentView(ll);
myAdView = new ImageView(this);
LinearLayout.LayoutParams childParam1 = new
LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0, 0.10f);
myAdView.setLayoutParams(childParam1);
....
View.OnClickListener handler = new View.OnClickListener() {
public void onClick(View v) {
switch (v.getId()) {
...
case R.id.menu3:
share();
break;
...
}
}
Here's share() function.
private void share(){
List<Intent> targetedShareIntents = new ArrayList<Intent>();
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("*/*");
List<ResolveInfo> resInfo =
this.getPackageManager().queryIntentActivities(intent, 0);
for (ResolveInfo resolveInfo : resInfo) {
........
if (packageName.toLowerCase().contains("twitter")){
targetedShareIntent.setType("*/*");
String location = "file://" + takeScreen(ll);
...
}
...
}
This is takeScreen(View v) function.
public String takeScreen(View c_view){
ll.removeView(adView1);
ll.addView(myAdView);
// create bitmap screen capture
Bitmap bitmap;
View v1 = c_view.getRootView();
v1.setDrawingCacheEnabled(true);
bitmap = v1.getDrawingCache();
String extr = Environment.getExternalStorageDirectory().toString();
File imageFile = new File(extr, "screen_" + System.currentTimeMillis() + ".jpg");
OutputStream fout = null;
try {
fout = new FileOutputStream(imageFile);
boolean saved = bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fout);
//Log.e("bitmap saved ?", saved + "!");
fout.flush();
fout.close();
MediaStore.Images.Media.insertImage(getContentResolver(), bitmap, "Screen", "screen");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
ll.removeView(myAdView);
ll.addView(adView1);
return imageFile.getPath();
}
As you can see, I'm removing adView and adding myAdView(imageView) just before the screenshot is taken in takeScreen() function. adView IS removed but imageVies is NOT added to the screenshot.
The imageView DOES appear on the screen just before chooserIntent(share intent) pop-up screen is displayed.
I have tried many other options like
added both views and just switched visibility. setVisibility(View.Gone, View.Visible)
tried creating bitmap with canvas instead of getDrawingCache (thinking that it could be a cache related problem)
Is taking screenshot or 'share intent' too much of work for the UI thread to be blocked?
Can anyone shed a light here? I am completely at a loss.
I found a way to get around this. I created a composite bitmap out of the background bitmap and the overlay(my ad image) bitmap. In case anyone is interested, here's the code.
public Bitmap screenShot(View view) {
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
Bitmap overlay = BitmapFactory.decodeResource(this.getResources() , R.drawable.my_ad);
canvas.drawBitmap(overlay, 100, 100, null);
return bitmap;
}
I want to create a page with dynamic control in windows phone.
While doing this I also want to show a progress bar
Below is my code
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
progressstackPanel.Visibility = Visibility.Visible;//progress bar
formScreen = this;
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
if (!isfst)
{
DrawScreen();
}
else
{
//xTitlePanel is only stack panel in my xaml with vertical orientation
xTitlePanel.UpdateLayout();
}
isfst = true;
progressstackPanel.Visibility = Visibility.Collapsed;
});
}
//Code of DrawScreen which is adding control to my stack panels
private void DrawScreen()
{
if (frm_getset.ChildList != null)
{
String[] arr = frm_getset.ChildList.Split(',');
xTitlePanel.Children.Clear();
PrepareControls prepcontrol = new PrepareControls();
foreach (AttributeGetSet a in _Attribute)
{
//this will return a stackpanel containing
// button/textbox etc.depending on a
StackPanel sp = prepcontrol.getControl(i, a.Label, a, formScreen);
try
{
xTitlePanel.Children.Add(sp);
///Here I get a eception only one control is added first one
/// for anyone it is getting a exception Argument
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
i += 1;
}
The system is adding only one control and when ever it try to execute xTitlePanel.Children.Add(sp); it will get an exception.
I solved the problem ,"xTitlePanel" is a StackPanel I created in my XAML. I found you can not add more that one element from Dispatcher to a control crated on xaml. Like that. so I have to create local stack and add controls to the that local stack panel then and after complete I add the local stack panel to xTitlePanel. NOW my code looks like below
filteredList = new List<FormGetSet>();
if (frm_getset.ChildList != null)
{
String[] arr = frm_getset.ChildList.Split(',');
foreach (String x in arr)
{
filteredList.Add(_template.list_fromgetset.Where(p => p.FormID.Contains(x.Trim())).ToList()[0]);
}
}
xTbox_FormNameHeader.Text = frm_getset.NAME;
_Attribute = new List<AttributeGetSet>();
_Attribute = frm_getset.list_attributegetset;
xTitlePanel.Children.Clear();
StackPanel spPanel = new StackPanel();
spPanel.Orientation = System.Windows.Controls.Orientation.Vertical;
spPanel.Background = new SolidColorBrush(Colors.Transparent);
//xTitlePanel.Children.Add(PrepareControls.getControl(1, "LABEL", "16"));
int i = 1;
// List<AttributeGetSet> _Attribute2 = new List<AttributeGetSet>();
foreach (AttributeGetSet a in _Attribute)
{
PrepareControls prepcontrol = new PrepareControls();
StackPanel sp= prepcontrol.getControl(i, a.Label, a, this);
try
{
spPanel.Children.Add(sp);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
//xTitlePanel.Background = new SolidColorBrush(Colors.White);
//_Attribute2.Add(a);
i += 1;
}
xTitlePanel.Children.Add(spPanel);
hi friends i am searching for how to crop image in titanium frame work,if some one has any relevent code then please help me.i will be greatly oblised with him..
thanks
i am android developer but now i ma working with titanium, am able to do in core android but not getting any relevant api able to work on titanium
android code is below only for posting my answer pls ignore it...
private void doCrop() {
final ArrayList<CropOption> cropOptions = new ArrayList<CropOption>();
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setType("image/*");
List<ResolveInfo> list = getPackageManager().queryIntentActivities( intent, 0 );
int size = list.size();
if (size == 0) {
Toast.makeText(this, "Can not find image crop app", Toast.LENGTH_SHORT).show();
return;
} else {
intent.setData(mImageCaptureUri);
intent.putExtra("outputX", 200);
intent.putExtra("outputY", 200);
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("scale", true);
intent.putExtra("return-data", true);
if (size == 1) {
Intent i = new Intent(intent);
ResolveInfo res = list.get(0);
i.setComponent( new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
startActivityForResult(i, CROP_FROM_CAMERA);
} else {
for (ResolveInfo res : list) {
final CropOption co = new CropOption();
co.title = getPackageManager().getApplicationLabel(res.activityInfo.applicationInfo);
co.icon = getPackageManager().getApplicationIcon(res.activityInfo.applicationInfo);
co.appIntent= new Intent(intent);
co.appIntent.setComponent( new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
cropOptions.add(co);
}
CropOptionAdapter adapter = new CropOptionAdapter(getApplicationContext(), cropOptions);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Choose Crop App");
builder.setAdapter( adapter, new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dialog, int item ) {
startActivityForResult( cropOptions.get(item).appIntent, CROP_FROM_CAMERA);
}
});
there is a method imageAsCropped on a TiBlob on IOS, you can check and see if it works on Android.
https://github.com/appcelerator/titanium_mobile/blob/master/iphone/Classes/TiBlob.m#L359