mirror image the captured photo - image

I am clicking the picture and the passing it through intent. But the image that I am displaying on the ImageView is the mirror image of the image captured. I have tried to implement RotateFlip method but the error appears saying Bitmap doesn't contain definition of RotateFlip.
{
var metrics = Resources.DisplayMetrics;
int windowWidth = metrics.WidthPixels;
int windowHeight = metrics.HeightPixels;
int reqWidth = (int)Math.Round(windowWidth*1.0f);
int reqHeight = (int)Math.Round(windowHeight*1.0f);
Bitmap photo = loadBitmapLowResolution(Image, reqWidth, reqHeight);
ExifInterface exif = new ExifInterface(Image);
int orientation = exif.GetAttributeInt(ExifInterface.TagOrientation, 90);
var rotation = exif.GetAttributeInt(ExifInterface.TagOrientation, (int)Orientation.Normal);
orientation = exif.GetAttributeInt(ExifInterface.TagOrientation, (int)Orientation.Rotate90);
// Rotate according to the orientation
Matrix matrix = new Matrix();
switch (orientation)
{
case (int)Orientation.Rotate90: matrix.PostRotate(90); break;
case (int)Orientation.Rotate180: matrix.PostRotate(180); break;
case (int)Orientation.Rotate270: matrix.PostRotate(270); break;
}
Bitmap photoRotated;
if (orientation != (int)Orientation.Normal)
{
photoRotated = Bitmap.CreateBitmap(photo, 0, 0, photo.Width, photo.Height, matrix, true);
}
else
{
photoRotated = photo;
}
// Apply center crop
int cropW = (int)(0.5 * (photoRotated.Width - photoRotated.Width/1.0f ) - 2);
int cropH = (int)(0.5 * (photoRotated.Height - photoRotated.Height/1.0f ) - 2);
cropW = cropW < 0 ? 0 : cropW;
cropH = cropH < 0 ? 0 : cropH;
//Log.Debug(TAG, "Creating a bitmap with size: " + (photoRotated.Width - 2 * cropW) + "x" + (photoRotated.Height - 2 * cropH) + " from a bitmap with size: " + photoRotated.Width + "x" + photoRotated.Height);
Bitmap photoCrop = Bitmap.CreateBitmap(photoRotated, cropW, cropH, photoRotated.Width - 2 * cropW, photoRotated.Height- 2 * cropH);
imageView.SetImageBitmap(photoCrop);
// Create your application here,
}
public static Bitmap loadBitmapLowResolution(string filePath, int reqWidth, int reqHeight)
{
BitmapFactory.Options options = new BitmapFactory.Options();
// First decode with inJustDecodeBounds=true to check dimensions
options.InJustDecodeBounds = true;
BitmapFactory.DecodeFile(filePath, options);
// Calculate inSampleSize
options.InSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.InJustDecodeBounds = false;
return BitmapFactory.DecodeFile(filePath, options);
}
private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight)
{
int height = options.OutHeight;
int width = options.OutWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth)
{
// Calculate ratios of height and width to requested height and width
int heightRatio = (int)Math.Round((float)height / (float)reqHeight);
int widthRatio = (int)Math.Round((float)width / (float)reqWidth);
// Choose the smallest ratio as inSampleSize value, this will guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}

The easiest way is to do it is using a Matrix;
public Bitmap HorizontalFlip(Bitmap bInput)
{
if (bInput == null) return null;
Matrix matrix = new Matrix();
matrix.PreScale(-1.0f, 1.0f);
return Bitmap.CreateBitmap(bInput, 0, 0, bInput.Width, bInput.Height, matrix, true);
}
Where bInput is the input bitmap that you wanna flip.

Related

How to refresh OnPaint() function; Window Update is not working

This is my code:
void CChildView::OnPaint()
{
CPaintDC dc(this);
CBitmap b; b.LoadBitmap(IDB_BITMAP1);
CDC memdc; memdc.CreateCompatibleDC(&dc);
auto prev = memdc.SelectObject(&b);
BITMAP bmp; b.GetBitmap(&bmp);
int bitmap_height = bmp.bmHeight;
int bitmap_width = bmp.bmWidth;
if (!painted) {
nrows = divide(bitmap_height, 8);
ncols = divide(bitmap_width, 8);
piece_height = bitmap_height / nrows;
piece_width = bitmap_width / ncols;
int number_of_tiles = nrows * ncols;
positions.resize(number_of_tiles);
std::iota(positions.begin(), positions.end(), 0);
empty = positions.size() - 1;//prazna pločica je zadnja
std::shuffle(positions.begin(), positions.end(), std::mt19937{ std::random_device{}() });
painted = true;
}
for (int i = 0; i < positions.size()-1; ++i) {
int row_dest = positions[i] / ncols;
int col_dest = positions[i] % ncols;
int row_src = i / ncols;
int col_src = i % ncols;
int x_src = col_src * piece_width;
int y_src = row_src * piece_height;
int x_dest = col_dest * piece_width;
int y_dest = row_dest * piece_height;
dc.BitBlt(x_dest, y_dest, piece_width, piece_height, &memdc, x_src, y_src, SRCCOPY);
dc.SelectObject(prev);
}
}
void CChildView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call def
CWnd::OnLButtonDown(nFlags, point);
//koordinate gdje je korisnik kliknuo
int row = point.y / piece_height;
int col = point.x / piece_width;
int empty_row = empty / ncols;
int empty_col = empty % ncols;
bool slide = false;
switch (abs(row - empty_row)) {
case 1:
if (abs(col==empty_col))
slide = true;
break;
case 0:
if (abs(col-empty_col==1))
slide = true;
break;
}
if (slide) {
int old_index = row * ncols + col;
positions[old_index] = positions[empty];
empty = old_index;
CWnd::InvalidateRect(NULL, FALSE);
CWnd::UpdateWindow();
}
}
I am trying to write a program that is called SlidingPuzzle. I managed to divide a bitmap into rectangles and shuffle them randomly. However, when I click on a rectangle there is no change. I suppose that UpdateWindow() is not working. It should refresh OnPaint() function. Can someone please help me, what am I doing wrong?

decodeSampledBitmapFromResource what to throw in parameters

Im trying to get my bitmap to fit in my imageview by using the tutorial on android devs but i dont know what to throw in this line imageView.setImageBitmap(
decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));
this is my full onActivityResult
if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE_CONTENT_RESOLVER) {
if (resultCode == RESULT_OK) {
// Image saved to a generated MediaStore.Images.Media.EXTERNAL_CONTENT_URI
String[] projection = {
MediaStore.MediaColumns._ID,
MediaStore.Images.ImageColumns.ORIENTATION,
MediaStore.Images.Media.DATA
};
Cursor c = getContentResolver().query(mPhotoUri, projection, null, null, null);
c.moveToFirst();
String photoFileName = c.getString(c.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeFile(photoFileName);
imageView.setImageBitmap(
decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));
} else if (resultCode == RESULT_CANCELED) {
// User cancelled the image capture
} else {
// Image capture failed, advise user
}
}
these are the methods on the android devs
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) >= reqHeight
&& (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
}
Im sorry if this is a not a good question but im trying to learn android developing at the moment.
fix it by making the two methods into a class.

Custom View in custom ViewGroup not displaying when offset in RelativeLayout

I have a custom view class (PinView) which is to be positioned within a custom ViewGroup (RightAngleTriangleView) based on some attributes. However, when it is placed relative to another view in a RelativeLayout, the PinView does not display. See code below:
RightAngleTriangleView
public class RightAngleTriangleView extends ViewGroup {
private static final String TAG = "RightAngleTriangleView";
private int pinOrientation;
private boolean isRightFilled, diagonalIsTopRightBottomLeft;
private Paint trianglePaint, pinPaint;
private Path trianglePath, pinPath;
private PointF triStart, triMiddle, triEnd;
private PinView pinView;
private float pinLengthDiff, pinThickness;
public RightAngleTriangleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setWillNotDraw(false); // remove default (non) drawing behaviour for ViewGroup
/*** extract XML attributes ***/
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.RightAngleTriangleView);
int fillColour = a.getColor(R.styleable.RightAngleTriangleView_fillColour,
context.getResources().getColor(android.R.color.darker_gray));
int fillPosition = a.getInt(R.styleable.RightAngleTriangleView_fillPosition,
context.getResources().getInteger(
R.integer.RightAngleTriangleView_fillPosition_left));
int diagonal = a.getInt(R.styleable.RightAngleTriangleView_diagonal,
context.getResources().getInteger(
R.integer.RightAngleTriangleView_diagonal_topLeftToBottomRight));
isRightFilled = fillPosition == context.getResources().getInteger(
R.integer.RightAngleTriangleView_fillPosition_right);
diagonalIsTopRightBottomLeft = diagonal == getContext().getResources().getInteger(
R.integer.RightAngleTriangleView_diagonal_topRightToBottomLeft);
pinOrientation = a.getInt(R.styleable.RightAngleTriangleView_pinOrientation,
context.getResources().getInteger(
R.integer.RightAngleTriangleView_pinOrientation_none));
a.recycle();
/*** setup drawing related variables ***/
trianglePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
trianglePaint.setStyle(Paint.Style.FILL_AND_STROKE);
trianglePaint.setColor(fillColour);
trianglePath = new Path();
trianglePath.setFillType(Path.FillType.EVEN_ODD);
triStart = new PointF();
triMiddle = new PointF();
triEnd = new PointF();
pinPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
pinPaint.setStyle(Paint.Style.FILL_AND_STROKE);
pinPaint.setColor(context.getResources().getColor(R.color.pin_color));
pinPath = new Path();
pinPath.setFillType(Path.FillType.EVEN_ODD);
// create pinView (if present)
if(pinOrientation != context.getResources().getInteger(
R.integer.RightAngleTriangleView_pinOrientation_none)){
pinView = new PinView(context, UiUtils.makeAttributeSet(context, getResourceId()));
addView(pinView);
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if(hasPin()){
// measure child to obtain 'wrapped' valid dimension
measureChild(pinView, widthMeasureSpec, heightMeasureSpec);
}
}
#Override
protected void onLayout (boolean changed, int left, int top, int right, int bottom){
Log.d(TAG, "onLayout() changed = " + changed);
if(hasPin()){
// use 'wrapped' valid dimension as pinThickness
if(pinView.isHorizontal()) {
pinThickness = pinView.getMeasuredHeight() / 2;
pinLengthDiff = (pinThickness * getWidth()) / getHeight();
}
else{
pinThickness = pinView.getMeasuredWidth() / 2;
pinLengthDiff = (pinThickness * getHeight()) / getWidth();
}
placePinView(left, top, right, bottom);
}
}
#Override
protected void onDraw(Canvas canvas){
// draw pin 'edge' if applicable
if(hasPin()){
pinPath.reset(); // remove any previously drawn paths
if(pinView.isHorizontal()){
pinPath.addRect((getWidth() - pinLengthDiff) / 2, (getHeight() - pinThickness) / 2,
(getWidth() + pinLengthDiff) / 2, (getHeight() + pinThickness) / 2,
Path.Direction.CW);
}
else{
pinPath.addRect((getWidth() - pinThickness) / 2, (getHeight() - pinLengthDiff) / 2,
(getWidth() + pinThickness) / 2, (getHeight() + pinLengthDiff) / 2,
Path.Direction.CW);
}
canvas.drawPath(pinPath, pinPaint);
}
// determine triangle vertices
if(diagonalIsTopRightBottomLeft){
// draw diagonal
triStart.set(getWidth(), 0);
triMiddle.set(0, getHeight());
// determine triEnd based on fill position
if(isRightFilled){
triEnd.set(getWidth(), getHeight());
}
else{
triEnd.set(0, 0);
}
}
else{
// draw diagonal
triStart.set(0, 0);
triMiddle.set(getWidth(), getHeight());
// determine triEnd based on fill position
if(isRightFilled){
triEnd.set(getWidth(), 0);
}
else{
triEnd.set(0, getHeight());
}
}
// draw triangle
trianglePath.reset(); // remove any previously drawn paths
trianglePath.moveTo(triStart.x, triStart.y);
trianglePath.lineTo(triMiddle.x, triMiddle.y);
trianglePath.lineTo(triEnd.x, triEnd.y);
trianglePath.close(); // automatically draw third side
canvas.drawPath(trianglePath, trianglePaint);
}
public boolean hasPin(){
return pinView != null;
}
private void placePinView(int left, int top, int right, int bottom){
int l, t, r, b, pinPosition;
int trbl = diagonalIsTopRightBottomLeft ? 1<<2 : 0;
int rightFilled = isRightFilled ? 1<<1 : 0;
int horizontal = pinView.isHorizontal() ? 1 : 0;
int result = trbl + rightFilled + horizontal;
// determine pin size and position
switch (result){
case 0: // diagonal = top-left to bottom-right, left-filled, pin vertical
t = top;
b = t + (int) (getHeight() - pinLengthDiff) / 2;
l = left + (int) (getWidth() - pinThickness)/2;
r = l + pinView.getMeasuredWidth();
pinPosition = getContext().getResources().getInteger(
R.integer.PinView_position_top);
break;
case 1: // diagonal = top-left to bottom-right, left-filled, pin horizontal
l = left + (int) (getWidth() + pinLengthDiff)/2;
r = right;
b = top + (int) (getHeight() + pinThickness)/ 2;
t = b - pinView.getMeasuredHeight();
pinPosition = getContext().getResources().getInteger(
R.integer.PinView_position_right);
break;
case 2: // diagonal = top-left to bottom-right, right-filled, pin vertical
t = top + (int) (getHeight() + pinLengthDiff) / 2;
b = bottom;
r = left + (int) (getWidth() + pinThickness)/2;
l = r - pinView.getMeasuredWidth();
pinPosition = getContext().getResources().getInteger(
R.integer.PinView_position_bottom);
break;
case 3: // diagonal = top-left to bottom-right, right-filled, pin horizontal
l = left;
t = top + (int) (getHeight() - pinThickness)/ 2;
r = l + (int) (getWidth() - pinLengthDiff) / 2;
b = t + pinView.getMeasuredHeight();
pinPosition = getContext().getResources().getInteger(
R.integer.PinView_position_left);
break;
case 4: // diagonal = top-right to bottom-left, left-filled, pin vertical
t = top + (int) (getHeight() + pinLengthDiff) / 2;
b = bottom;
l = left + (int) (getWidth() - pinThickness)/2;
r = l + pinView.getMeasuredWidth();
pinPosition = getContext().getResources().getInteger(
R.integer.PinView_position_bottom);
break;
case 5: // diagonal = top-right to bottom-left, left-filled, pin horizontal
l = left + (int) (getWidth() + pinLengthDiff)/2;
t = top + (int) (getHeight() - pinThickness)/ 2;
r = right;
b = t + pinView.getMeasuredHeight();
pinPosition = getContext().getResources().getInteger(
R.integer.PinView_position_right);
break;
case 6: // diagonal = top-right to bottom-left, right-filled, pin vertical
t = top;
b = t + (int) (getHeight() - pinLengthDiff) / 2;
r = left + (int) (getWidth() + pinThickness)/2;
l = r - pinView.getMeasuredWidth();
pinPosition = getContext().getResources().getInteger(
R.integer.PinView_position_top);
break;
case 7: // diagonal = top-right to bottom-left, right-filled, pin horizontal
l = left;
r = l + (int) (getWidth() - pinLengthDiff) / 2;
b = top + (int) (getHeight() + pinThickness)/2;
t = b - pinView.getMeasuredHeight();
pinPosition = getContext().getResources().getInteger(
R.integer.PinView_position_left);
break;
default:
l = left;
t = top;
r = right;
b = bottom;
pinPosition = -1;
break;
}
// remeasure / resize pinView accounting for correct unspecified dimension
measureChild(pinView, MeasureSpec.makeMeasureSpec(r - l, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(b - t, MeasureSpec.EXACTLY));
pinView.setPosition(pinPosition); // ensure that pinName is in correct position
pinView.layout(l, t, r, b); // position pinView
}
private int getResourceId(){
int trbl = diagonalIsTopRightBottomLeft ? 1<<2 : 0;
int rightFilled = isRightFilled ? 1<<1 : 0;
int horizontal = pinOrientation == getContext().getResources().getInteger(
R.integer.RightAngleTriangleView_pinOrientation_horizontal) ? 1 : 0;
int result = trbl + rightFilled + horizontal;
Log.d(TAG, "getResourceId(): result = " + result);
switch (result){
case 0: // diagonal = top-left to bottom-right, left-filled, pin vertical
return R.xml.pinview_vertical_namebelow;
case 1: // diagonal = top-left to bottom-right, left-filled, pin horizontal
return R.xml.pinview_horizontal;
case 2: // diagonal = top-left to bottom-right, right-filled, pin vertical
return R.xml.pinview_vertical;
case 3: // diagonal = top-left to bottom-right, right-filled, pin horizontal
return R.xml.pinview_horizontal_namebelow;
case 4: // diagonal = top-right to bottom-left, left-filled, pin vertical
return R.xml.pinview_vertical_namebelow;
case 5: // diagonal = top-right to bottom-left, left-filled, pin horizontal
return R.xml.pinview_horizontal_namebelow;
case 6: // diagonal = top-right to bottom-left, right-filled, pin vertical
return R.xml.pinview_vertical;
case 7: // diagonal = top-right to bottom-left, right-filled, pin horizontal
return R.xml.pinview_horizontal;
default:
return -1;
}
}
}
PinView
public class PinView extends RelativeLayout {
private TextView pinNameView, signalTextView;
private boolean isHorizontal;
public PinView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
/*** extract XML attributes ***/
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.PinView);
boolean nameBelow = a.getBoolean(R.styleable.PinView_nameBelow, false);
int orientation = a.getInt(R.styleable.PinView_orientation, 0);
int position = a.getInt(R.styleable.PinView_position, -1);
isHorizontal = orientation == 0;
a.recycle();
/*** create children ***/
LinearLayout backgroundLayout = new LinearLayout(context);
backgroundLayout.setId(R.id.pinview_backgroundlayout);
backgroundLayout.setBackgroundColor(context.getResources().getColor(R.color.pin_color));
if(isHorizontal){
pinNameView = new TextView(context);
signalTextView = new TextView(context);
}
else{
pinNameView = new VerticalTextView(context);
signalTextView = new VerticalTextView(context);
}
pinNameView.setId(R.id.pinview_pinname);
pinNameView.setTextColor(context.getResources().getColor(android.R.color.black));
signalTextView.setId(R.id.pinview_signaltext);
signalTextView.setTextColor(context.getResources().getColor(android.R.color.black));
signalTextView.setBackgroundColor(context.getResources().getColor(R.color.pin_sig_color));
/*** determine children layouts and positions ***/
LayoutParams lpSigText = new LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
backgroundLayout.addView(signalTextView, lpSigText); // add signalView to backgroundLayout, NOT this view
LayoutParams lpBackgroundLayout;
if(isHorizontal){
lpBackgroundLayout = new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
}
else{
lpBackgroundLayout = new LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
}
LayoutParams lpPinName = new LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
// place pin name accordingly
if(nameBelow){
addView(backgroundLayout, lpBackgroundLayout);
if(isHorizontal){
lpPinName.addRule(RelativeLayout.BELOW, backgroundLayout.getId());
}
else{
lpPinName.addRule(RelativeLayout.RIGHT_OF, backgroundLayout.getId());
}
addView(pinNameView, lpPinName);
setPosition(position);
}
else{
addView(pinNameView, lpPinName);
setPosition(position);
if(isHorizontal){
lpBackgroundLayout.addRule(RelativeLayout.BELOW, pinNameView.getId());
}
else{
lpBackgroundLayout.addRule(RelativeLayout.RIGHT_OF, pinNameView.getId());
}
addView(backgroundLayout, lpBackgroundLayout);
}
}
public void setPosition(int position){
// align pin name according to pin position on device
LayoutParams params = (RelativeLayout.LayoutParams) pinNameView.getLayoutParams();
switch(position){ // pin's position relative to parent device
case 2: // top
params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
break;
case 3: // bottom
params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
break;
case 0: // left
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
break;
case 1: // right
params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
break;
default:
break;
}
}
public void setData(DevicePin pin){
pinNameView.setText(pin.name);
signalTextView.setText(pin.data);
// always create new animation, otherwise it will need to be reset
Animation anim = null;
switch (pin.direction){
case LEFT:
anim = AnimationUtils.loadAnimation(getContext(), R.anim.pin_transition_left);
break;
case RIGHT:
anim = AnimationUtils.loadAnimation(getContext(), R.anim.pin_transition_right);
break;
case UP:
anim = AnimationUtils.loadAnimation(getContext(), R.anim.pin_transition_up);
break;
case DOWN:
anim = AnimationUtils.loadAnimation(getContext(), R.anim.pin_transition_down);
break;
}
if(pin.startBehaviour == DevicePin.AnimStartBehaviour.DELAY){
if(pin.animationDelay == -1){
anim.setStartOffset(anim.getDuration());
}
else{
anim.setStartOffset(pin.animationDelay);
}
}
if(pin.action == DevicePin.PinAction.STATIONARY){
anim.setDuration(0);
}
if(pin.animListener != null){
anim.setAnimationListener(pin.animListener);
}
if(anim != null){
signalTextView.setAnimation(anim);
}
}
public boolean isHorizontal(){
return isHorizontal;
}
}
Activity XML
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<view
class="org.ricts.abstractmachine.ui.device.RightAngleTriangleView"
android:id="#+id/edge"
android:layout_width="122px"
android:layout_height="150px"
custom:diagonal = "topLeftToBottomRight"
custom:fillPosition = "right"
custom:fillColour="#color/mux_fill_color"
custom:pinOrientation = "vertical"
/>
<view
class="org.ricts.abstractmachine.ui.device.RightAngleTriangleView"
android:id="#+id/edge2"
android:layout_width="122px"
android:layout_height="150px"
android:layout_toRightOf="#+id/edge"
custom:diagonal = "topLeftToBottomRight"
custom:fillPosition = "right"
custom:fillColour="#color/mux_fill_color"
custom:pinOrientation = "vertical"
/>
<view
class="org.ricts.abstractmachine.ui.device.RightAngleTriangleView"
android:id="#+id/edge3"
android:layout_width="122px"
android:layout_height="150px"
android:layout_below="#+id/edge"
custom:diagonal = "topLeftToBottomRight"
custom:fillPosition = "right"
custom:fillColour="#color/mux_fill_color"
custom:pinOrientation = "vertical"
/>
<view
class="org.ricts.abstractmachine.ui.device.PinView"
android:id="#+id/pin"
android:layout_width="58px"
android:layout_height="64px"
android:layout_below="#+id/edge"
android:layout_toRightOf="#+id/edge3"
custom:orientation="vertical"
custom:position="top"
/>
</RelativeLayout>
The code above is the XML for an Activity to highlight the problem. I have also taken a screenshot of the problem (below). The triangle in the top-most corner is fine and displays the inner PinView. However, the other two (below and at the right of the first one) do not display the PinView even though the code is exactly the same and I have confirmed by Log that the intended PinView positions seem ok.
Problem Screenshot
What am I doing wrong?
It turns out that I was using absolute values when calling View.layout(l,t,r,b) instead of relative ones. I now use the relative values and it works!

Save image with Processing

I'm trying to save an image after certain time, the problem is that the image size is bigger than the display so when I use the save or saveFrame function it only saves the image that I can see in the display. There is any other way to save the whole image?
This is my code:
PImage picture, pictureFilter, img;
int total, cont, current;
ArrayList<ArrayList<Position>> columns;
String[] fontList;
public class Position {
public int x;
public int y;
}
void setup() {
fontList = PFont.list();
picture = loadImage("DSC05920b.JPG");
pictureFilter = loadImage("filtrePort2.jpg");
frame.setResizable(true);
size(picture.width, picture.height);
columns = new ArrayList<ArrayList<Position>>();
for(int i = 0; i < picture.width; i++) {
ArrayList<Position> row = new ArrayList<Position>();
for(int j = 0; j < picture.height; j++){
Position p = new Position();
p.x = i;
p.y = j;
row.add(p);
}
columns.add(row);
}
total = picture.width * picture.height;
cont = total;
current = 0;
img = createImage(picture.width, picture.height, RGB);
}
float randomLetter() {
float value = 23;
boolean found = false;
while(!found) {
value = random(48, 122);
if(value >48 && value <58) found = true;
if(value >65 && value <91) found = true;
if(value >97 && value <123) found = true;
}
return value;
}
void draw() {
int x = int(random(0, columns.size()));
ArrayList<Position> rows = columns.get(x);
int y = int(random(0, rows.size()));
Position p = rows.get(y);
color c = pictureFilter.get(p.x, p.y);
int r = (c >> 16) & 0xFF; // Faster way of getting red(argb)
if(r < 240) {
PFont f = createFont(fontList[int(random(0,fontList.length))],random(5, 24),true);
textFont(f);
fill(picture.get(p.x,p.y));
char letter = (char) int(randomLetter());
text(letter, p.x, p.y);
}
if(rows.size() == 1) {
if(columns.size() == 1) {
saveFrame("lol.jpg");
columns.remove(x);
} else {
columns.remove(x);
}
} else {
println(rows.size());
rows.remove(y);
}
--cont;
float percent = float(total-cont)/float(total)*100;
if(int(percent) != current) {
current = int(percent);
save("image_" + current + ".jpg");
}
println("DONE: " + (total-cont) + "/" + total + " Progress: " + percent + "%");
}
The code do a lot of stuff but the part that its not working well is at the final when I check if the percentage have been increased in order to save the image
You can write this into a PGraphics context - aka a graphics buffer.
The buffer can be as big as you need it to be, and you can choose whether to draw it on the screen or not..
// Create the buffer at the size you need, and choose the renderer
PGraphics pg = createGraphics(myImage.width, myImage.height, P2D);
// Wrap all your drawing functions in the pg context - e.g.
PFont f = createFont(fontList[int(random(0,fontList.length))],random(5, 24),true);
textFont(f);
pg.beginDraw();
pg.fill(picture.get(p.x,p.y));
char letter = (char) int(randomLetter());
pg.text(letter, p.x, p.y);
pg.endDraw();
// Draw your PG to the screen and resize the representation of it to the screen bounds
image(pg, 0, 0, width, height); // <-- this wont actually clip/resize the image
// Save it
pg.save("image_" + current + ".jpg");
The PImage class contains a save() function that exports to file. The API should be your first stop for questions like this.

Image gallery assistance if you may

I created an image gallery that works great, the only problem I have is that I don't know how to set up my program so when you open it it opens with the pictures as thumbnails and if you click on the thumbnails the image expands.
int maxImages;
int imageIndex;
// Declaring an array of images.
PImage[] images;
void setup() {
size(600,400);
images = new PImage[maxImages];
maxImages = 2;
imageIndex = 0; // Initial image to be displayed is the first
for (int i = 0; i < images.length; i ++ ) {
images[i] = loadImage( "changeling" + i + ".jpg" );
}
}
void draw() {
// Displaying one image
image(images[imageIndex],0,0);
}
Here it's the idea, to show the images i'm setting them whit a width and height of 100 you can use any value or your own algorithm to get the best sizes.
Knowing the space in the sketch that every image occupies I can know when the mouse was inside one of them when an mouse click event happen. Then I proceed to expand the image by doubling the size until it reaches a good size comparing whit the screen size, Again you can use you own value or algorithm to get the best expansion ratio.
Once the mouse it's clicked again when an image is expanded it goes back to the thumbnail again.
Hope this can be useful.
int maxImages;
int imageIndex;
boolean imageExpand;
// Declaring an array of images.
PImage[] images;
void setup() {
size(600,400);
maxImages = 2;
imageIndex = 0; // Initial image to be displayed is the first
boolean imageExpand;
images = new PImage[maxImages];
imageExpand = false;
for (int i = 0; i < images.length; i ++ ) {
images[i] = loadImage( "changeling" + i + ".jpg" );
}
}
void draw() {
if(!imageExpand){
showThumbnail();
}
}
void mouseClicked(){
if(!imageExpand){
for(int i=0; i < images.length; i++){
if((images[i].X > mouseX) && (images[i].X + images[i].width < mouseX)){
if((images[i].Y > mouseY) && (images[i].Y + images[i].height < mouseY)){
expandImage(images[i]);
imageExpand = true;
}
}
}
}
else{
imageExpand = false;
showThumbnail();
}
}
void expandImage(PImage myImage){
int largeWidth, largeHeight;
while((myImage.width * 2 < 600) && (myImage.height * 2 < 400)){
largeWidth = myImage.width * 2;
largeWidth = myImage.height * 2;
}
image(myImage, 0, 0, largeWidth, largeHeight);
}
void showThumbnail(){
int posX = 0, posY = 0, lastImage = 0;
for(int i=0; i < images.length; i++){
if(posX + 100 < 600){
image(images[i], posX, posY, 100, 100);
posX = posX + 100;
}
else{
posX = 0;
posY = posY + 100;
image(images[i], posX, posY, 100, 100);
}
}
}
Regards Jose

Resources