I am attempting to finger draw on a transparent bitmap. The canvas Im using draws the image just fine, but when I save the image, the image shows like below, with all the horizontal transparent lines.
I draw using the following code.
private void doDraw(Canvas canvas) {
mOffScreenCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
for(int index = 0; index < mAnnotations.size(); index++) {
InkAnnotation annotation = mAnnotations.get(index);
annotation.draw(mOffScreenCanvas, ActivityPageToolBar.mCurrentTool.paint());
}
if(canvas != null && mSurface != null) {
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
canvas.drawBitmap(mSurface, 0, 0, mPaint);
}
}
The file is saved using
Bitmap saveBitmap = Bitmap.createBitmap(map);
Canvas c = new Canvas(saveBitmap);
c.drawColor(0xFFFFFFFF);
c.drawBitmap(map,0,0,null);
i use standard file saving to save it
try {
FileOutputStream out = handle.outputStream();
if(handle.fileName().contains(".png")) {
((Bitmap) handle.data()).compress(CompressFormat.PNG, quality, out);
} else if(handle.fileName().contains(".jpg") || handle.fileName().contains(".jpeg")) {
((Bitmap) handle.data()).compress(CompressFormat.JPEG, quality, out);
} else {
((Bitmap) handle.data()).compress(CompressFormat.WEBP, quality, out);
}
out.flush();
out.close();
} catch(Exception e) {
e.printStackTrace();
}
Any way to fix this issue? At the same time I am embedding the bitmap into a pdf and the colors are darker than they should be.
This is what the image looks like on the screen before I save it. The background is irrelevant, i can draw to the screen just fine, but when it save it to a png it looks messed up.
I solved this by taking the points I created on the surfaceview and creating a new bitmap from those points. There must be something the surface it doing to its bitmap to cause this.
Related
I am developing android application drag and drop sticker and resize sticker after capturing image. I have problem with sticker position is change after saving image.it is move almost 20 dp down after saving.
i have use https://github.com/siralam/CameraViewPlus for camera2. and https://github.com/wuapnjie/StickerView for sticker.
here is my function draw sticker over it and save.
downloadButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final ICallback callback = new ICallback() {
#Override
public void done(Exception e) {
if (e == null) {
DebugLog.e("onImageSavedCallback: image saved!");
//showCustomDialog(layoutView);
// closeButton.performClick();
showCustomDialog();
cameraView.start();
} else {
DebugLog.e("onImageSavedCallback: error saving image: " + e.getMessage());
showSnackBar("Error saving image", Snackbar.LENGTH_SHORT);
}
}
};
stickerView.setLocked(true);
stickerView.invalidate();
Bitmap newBitmap = null;
Bitmap bitmap = CommonMethods.getBitmapFromView(stickerView);
try {
Bitmap.Config config = imageBitmap.getConfig();
if (config == null) {
config = Bitmap.Config.ARGB_8888;
}
newBitmap = Bitmap.createBitmap(imageBitmap.getWidth(), imageBitmap.getHeight(), config);
Canvas canvas = new Canvas(newBitmap);
// Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG);
canvas.drawBitmap(imageBitmap, 0, 0, null);
canvas.drawBitmap(bitmap, 0, 0, null);
} catch (Exception ex) {
ex.printStackTrace();
}
int t = 1;
ImageSaver imageSaver = new ImageSaver(
newBitmap,
getExternalFilesDir(null),
callback,
t
);
mBackgroundHandler.post(imageSaver);
}
});
I have issue with sticker change itz position after saving image. image will show out of bound when image scale type would be center crop. corner portion cutting down.
First Image is before save.
Second Image is after save.
I figure out answer. problem is bitmap size smaller then sticker view. so it possible when i am overlay sticker on bitmap position should be start from position X, that is position 0, Sticker view is full match parent and background is transparent, it overlay on bitmap.
sticker view size is 1080 x 2061 and bitmap size is 1080 x 1920. it is possible position should be different after save result.
Problem Solved.
I am trying to capture a photo and after that, allow to the user to add some effects, draw, drag other assets to the image, add text, etc. Like snapchat camera.
I have followed the Camera 2 API sample. The major part of the code is at
Camera2BasicFragment.java
I have achieved the capture and preview image, but the example set the image in a TextureView, but I do not have idea how to continue to manipulate the image.
I dont know if I should use a TextureView or a Canvas or a SurfaceView.
An example of the final image result that I want:
Thanks in advance.
Capture your photo , save your image. Then in an ImageView you can apply all kind of effects that you want using Bitmap and ColorMatrix.
Here I give a small sample to make an image grayscale
public void toGrayscale() {
ColorMatrix matrix = new ColorMatrix();
matrix.setSaturation(0);
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix);
imageView.setColorFilter(filter);
}
After applying the effects just save drawable to image file like this:
public void saveDrawable(ImageView imageView) throws FileNotFoundException {
Bitmap bitmap = getBitmapFromImageView(imageView);
OutputStream fOut = null;
try {
fOut = new FileOutputStream(absolutePath);
bitmap.compress(Bitmap.CompressFormat.JPEG, 95, fOut);
} finally {
if (fOut != null) {
try {
fOut.close();
} catch (IOException e) {
//report error
}
}
}
}
#NonNull
private Bitmap getBitmapFromImageView(ImageView imageView) {
Drawable drawable = imageView.getDrawable();
Rect bounds = drawable.getBounds();
Bitmap bitmap = Bitmap.createBitmap(bounds.width(), bounds.height(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.draw(canvas);
return bitmap;
}
There is a good library that will help you https://github.com/chrisbanes/PhotoView
To draw with a finger this question how to draw line on imageview along with finger in android should help you
Hope its helps!!
I am programmatically drawing to a canvas using data entered by the user. Once all of the data is entered, the user can flip through the images and they will be drawn to the canvas. The user has the option to save all of the images(could be several hundred). I use a runnable that runs on the UI thread that will draw and save each image(since you can't draw to a canvas from an AsyncTask). This works, but the problem I am having is if while the saving is going on, the user turns off the screen or minimizes the app. This causes the jpegs to just be black. I would like the saving to be something that could run in the background and still work.
Code used to draw to canvas and save image:
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Bitmap bitmap;
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
canvas.setBitmap(bitmap);
// draw everything here
OutputStream stream = new FileOutputStream(imageName + ".jpg");
bitmap.compress(CompressFormat.JPEG, 100, stream);
stream.close();
}
So, is there a way for images to be drawn and saved to a file in the background while the canvas is not visible? Any help would be appreciated!
I think you can use this:
signLayout.setDrawingCacheEnabled(true); //signLayout is layout that contains image you want to save
// Save image from layout
String path = "sdcard0/test/test.jpg"; //file path you want to save
gestureSign.save(signLayout, path);
SAVE METHOD
//Save to path
public void save(View v, String SavePath)
{
if(mBitmap == null)
{
mBitmap = Bitmap.createBitmap (layoutSign.getWidth(), layoutSign.getHeight(), Bitmap.Config.RGB_565);;
}
Canvas canvas = new Canvas(mBitmap);
try
{
FileOutputStream mFileOutStream = new FileOutputStream(SavePath);
v.draw(canvas); //Lay toan bo layout
mBitmap.compress(Bitmap.CompressFormat.PNG, 100, mFileOutStream);
mFileOutStream.flush();
mFileOutStream.close();
}
catch(Exception e)
{
Log.v("log_tag", e.toString());
}
}
On android I am drawing into a android.graphics.Picture then save the Picture to a file. Later I reload the picture into memory and draw it to the canvas. I noticed that Bitmaps were never drawing. And after much debugging I managed to narrow down the problem to Picture.writeToStream and Picture.createFromStream. It seems that Bitmaps drawn into the picture don't get reloaded properly. Below is sample code I wrote to show the problem. In this sample my canvas is not hardware accelerated.
So my questions are as follows:
Am I doing something wrong?
Is this an Android bug? I filed the bug report https://code.google.com/p/android/issues/detail?id=54896 because I think this is.
Any known workaround?
#Override
protected void onDraw(Canvas canvas)
{
try
{
Picture picture = new Picture();
// Create a bitmap
Bitmap bitmap = Bitmap.createBitmap( 100, 100, Config.ARGB_8888);
Canvas bitmapCanvas = new Canvas(bitmap);
bitmapCanvas.drawARGB(255, 0, 255, 0);
// Draw the bitmap to the picture's canvas.
Canvas pictureCanvas = picture.beginRecording(canvas.getWidth(), canvas.getHeight());
RectF dstRect = new RectF(0, 0, 200, 200);
pictureCanvas.drawBitmap(bitmap, null, dstRect, null);
picture.endRecording();
// Save the Picture to a file.
File file = File.createTempFile("cache", ".pic");
FileOutputStream os = new FileOutputStream(file);
picture.writeToStream(os);
os.close();
// Read the picture back in
FileInputStream in = new FileInputStream(file);
Picture cachedPicture = Picture.createFromStream(in);
// Draw the cached picture to the view's canvas. This won't draw the bitmap!
canvas.drawPicture(cachedPicture);
// Uncomment the following line to see that Drawing the Picture without reloading
// it from disk works fine.
//canvas.drawPicture(picture);
}
catch (Exception e)
{
}
}
I did find an answer to this question after looking at the native android code that backs the Bitmap. Android only can only save certain types of bitmaps to the picture. This is because the SkBitmap class only supports certain types of inputs that result in a bitmap that can be saved to a Picture. So in this can I can workaround the problem by providing those magical inputs. Use a bitmap that is saved to disk and call BitmapFactory.decodeFileDescriptor to create it.
private Bitmap createReusableBitmap(Bitmap inBitmap)
{
Bitmap reuseableBitmap = null;
if (inBitmap== null)
return null;
try
{
// The caller is responsible for deleting the file.
File tmpBitmapFile = File.createTempFile("bitmap", ".png");
setBitmapPath(tmpBitmapFile.getAbsolutePath());
FileOutputStream out = new FileOutputStream(tmpBitmapFile);
boolean compressed = inBitmap.compress(CompressFormat.PNG, 100, out);
out.close();
if (compressed)
{
// Have to create a purgeable bitmap b/c that is the only kind that works right when drawing into a
// Picture. After digging through the android source I found decodeFileDescriptor will create the one we need.
// See https://github.com/android/platform_frameworks_base/blob/master/core/jni/android/graphics/BitmapFactory.cpp
// In short we have to give the options inPurgeable=true inInputShareable=true and call decodeFileDescriptor
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
options.inInputShareable = true;
options.inPurgeable = true;
options.inSampleSize = 1;
options.inScaled = false;
options.inMutable = false;
options.inTempStorage = DraftRenderer.tempStorage;
FileInputStream inStream = new FileInputStream(tmpBitmapFile);
FileDescriptor fd = inStream.getFD();
reuseableBitmap = BitmapFactory.decodeFileDescriptor(fd, null, options);
inStream.close();
}
} catch (Exception e) {
}
return reuseableBitmap;
}
Note: a picture created from an input stream cannot be replayed on a hardware accelerated canvas.
Picture.createFromStream(InputStream stream)
you can use canvas.isHardwareAccelerated() to detect hardware accelerated or not.
My app is a basic drawing app. User can draw on a Canvas and save the image as a PNG. He can load the earlier drawn images and edit them.
I was able to do the first part. that is, the user can draw and save the image on the sdcard. I'm having trouble loading the saved png file on to the Canvas and drawing on it.
here is the run method in my SurfaceView class.
public void run() {
Canvas canvas = null;
while (running) {
try {
canvas = holder.lockCanvas(null);
synchronized (holder) {
if(mBitmap == null){
mBitmap = Bitmap.createBitmap (1, 1, Bitmap.Config.ARGB_8888);;
}
final Canvas c = new Canvas (mBitmap);
c.drawColor(Color.WHITE);
//pad.onDraw(canvas);
Paint p = new Paint();
p.setColor(Color.GRAY);
for(double x = 0.5;x < c.getWidth();x += 30) {
c.drawLine((float)x, 0, (float)x, c.getHeight(), p);
}
for(double y= 0.5;y < c.getHeight();y += 30) {
c.drawLine(0, (float)y, c.getWidth(), (float)y, p);
}
pad.onDraw(c);
canvas.drawBitmap (mBitmap, 0, 0, null);
}
} finally {
if (canvas != null) {
holder.unlockCanvasAndPost(canvas);
}
}
}
}
I tried loading the png to the 'mBitmap', but it didn't work.
Any help appreciated.
thank you!
In your code you are not loading the image from sd card at all, is this intentional? This is how you open an image form SD card:
mBitmap = BitmapFactory.decodeFile("/sdcard/test.png");