How to draw circles on different positions using onTouchEven() in android? - android

I am trying to draw a circles at point where the user touches.I am using onTouchEvent() to get the x y coordinates of the touch.The following code adds a circle in right corner of the screen.But when i use invalidate() function before the 'break;' statement in the onTouchEvent(), circle appears but when i touch at other position the previous circle gets erased and and a new circle is drawn at the new touched position.
How can I modify this code so that on every ACTION_DOWN onTouchEvent() a circle is drawn on that point and previously drawn circle also not erased.
public class TestView3 extends View {
private static final String TAG = "TestView3";
Paint paint = new Paint();
float mX,mY;
public TestView3(Context context, AttributeSet attributeSet){
super(context);
Log.d(TAG, "TestView3: constructor called");
paint.setColor(Color.BLACK);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.d(TAG, "onDraw: called");
//canvas.drawLine(0,0,20,20,paint);
//canvas.drawLine(20,0,0,20,paint);
canvas.drawCircle(mX,mY,10,paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
Log.d(TAG, "onTouchEvent: Action_down happend");
mX = x;
mY = y;
break;
}
return true;
}
}

You have to store your circles in a list and draw each of them in the onDraw method.
The following edited code worked for me.
public class TestView3 extends View {
private static final String TAG = "TestView3";
Paint paint = new Paint();
float mX,mY;
Bitmap mBitmap;
Canvas mCanvas;
ArrayList<Point> arrayList = new ArrayList<>();
public TestView3(Context context, AttributeSet attributeSet){
super(context);
Log.d(TAG, "TestView3: constructor called");
paint.setColor(Color.BLACK);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.d(TAG, "onDraw: called");
//canvas.drawLine(0,0,20,20,paint);
//canvas.drawLine(20,0,0,20,paint);
for(int i = 0;i < arrayList.size();i++){
Point point = arrayList.get(i);
canvas.drawCircle(point.x,point.y,10,paint);
// Draw line with next point (if it exists)
if (i + 1 < arrayList.size()) {
Point next = arrayList.get(i + 1);
canvas.drawLine(point.x, point.y, next.x, next.y, paint);
}
}
// canvas.drawCircle(mX,mY,10,paint);
}
/* protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mBitmap = Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}*/
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
Log.d(TAG, "onTouchEvent: Action_down happend");
mX = x;
mY = y;
arrayList.add(new Point((int)x,(int)y));
invalidate();
break;
}
return true;
}
}

Related

How to measure hand drawn image on canvas in Android?

I am hand drawing images on a canvas and then converting them to a bitmap. Then, I am dragging this on screen. That's all fine, What I want is onTouchEvent to draw a rectangle round this image/s but NOT the whole canvas. So I'm wondering if I can measure the drawing width and height and subtract this from canvas width and height but I'm struggling and not sure How can I achieve this? Unless there's a better idea someone can suggest.
private static class DrawingView extends View {
float x = 0f,y = 0f;
float dX,dY;
Paint paint;
public DrawingView(Context context){
super(context);
bitmap = BitmapFactory.decodeResource(context.getResources(), R.id.main);
paint = new Paint();
}
public boolean onTouchEvent(MotionEvent event){
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
dX = this.getX() - event.getRawX();
dY = this.getY() - event.getRawY();
invalidate();
break;
case MotionEvent.ACTION_MOVE:
this.setX(event.getRawX() + dX);
this.setY(event.getRawY() + dY);
invalidate();
break;
case MotionEvent.ACTION_UP:
invalidate();
break;
}
return true;
}
#Override
public void onDraw(Canvas canvas) {
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.BLACK);
canvas.drawBitmap(bitmap, x, y, paint);
float left = (x + (bitmap.getWidth()/2));
float top = (y + (bitmap.getHeight()/2));
float right = bitmap.getWidth() - left;
float bottom = bitmap.getHeight() - top;
canvas.drawRect(left, top, right, bottom, paint);
}
}//End of inner class
My drawing class
public class DrawView extends View {
private Paint drawPaint, canvasPaint;
private Canvas drawCanvas;
private Bitmap canvasBitmap;
private SparseArray<Path> paths;
public DrawView(Context context) {
super(context);
setupDrawing();
}
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
setupDrawing();
}
public DrawView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setupDrawing();
}
private void setupDrawing() {
paths = new SparseArray<>();
drawPaint = new Paint();
drawPaint.setColor(Color.BLACK);
drawPaint.setAntiAlias(true);
drawPaint.setStrokeWidth(9);
drawPaint.setStyle(Paint.Style.STROKE);
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);
canvasPaint = new Paint(Paint.DITHER_FLAG);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
drawCanvas = new Canvas(canvasBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
for (int i = 0; i < paths.size(); i++) {
canvas.drawPath(paths.valueAt(i), drawPaint);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int index = event.getActionIndex();
int id = event.getPointerId(index);
final Point p = new Point();
Path path;
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
path = new Path();
path.moveTo(event.getX(index), event.getY(index));
paths.put(id, path);
break;
case MotionEvent.ACTION_MOVE:
for (int i=0; i<event.getPointerCount(); i++) {
id = event.getPointerId(i);
path = paths.get(id);
if (path != null) path.lineTo(event.getX(i), event.getY(i));
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
path = paths.get(id);
if (path != null) {
drawCanvas.drawPath(path, drawPaint);
paths.remove(id);
}
setPenEnabled(true);
break;
default:
return false;
}
invalidate();
return true;
}
/**
* change path color here
*/
public void setPathColor(int color) {
drawPaint.setColor(color);
}
//Clear screen
public void clear() {
canvasBitmap.eraseColor(Color.TRANSPARENT);
paths.clear();
invalidate();
System.gc();
}
}//End of Class

Android: How to make a canvas on only part of the screen dynamically?

In android, how can I make a drawable canvas appear on only part of the screen when a user does an action?
My end-goal is to dynamically insert into the layout a bar that, when the user touches it, a particular text will be drawn on the bar.
I've searched, and I've only seen ways where a canvas is handled as a layout itself; not as a View that can be added to an activity. And my understanding is that to make it only part of the screen, I'd somehow have to handle it as a View that can be added to a layout. How do I do this?
For creating a canvas create the custom view like as below:
public class CanvasView extends View {
public int width;
public int height;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
Context context;
private Paint mPaint;
private float mX, mY;
private static final float TOLERANCE = 5;
public CanvasView(Context c, AttributeSet attrs) {
super(c, attrs);
context = c;
// we set a new Path
mPath = new Path();
// and we set a new Paint with the desired attributes
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeWidth(4f);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// your Canvas will draw onto the defined Bitmap
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
// override onDraw
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// draw the mPath with the mPaint on the canvas when onDraw
canvas.drawPath(mPath, mPaint);
}
// when ACTION_DOWN start touch according to the x,y values
private void startTouch(float x, float y) {
mPath.moveTo(x, y);
mX = x;
mY = y;
}
// when ACTION_MOVE move touch according to the x,y values
private void moveTouch(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOLERANCE || dy >= TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
public void clearCanvas() {
mPath.reset();
invalidate();
}
// when ACTION_UP stop touch
private void upTouch() {
mPath.lineTo(mX, mY);
}
//override the onTouchEvent
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startTouch(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
moveTouch(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
upTouch();
invalidate();
break;
}
return true;
}
}
After that use this canvasView into the xml file:
<com.example.canvasdemo.CanvasView
android:id="#+id/signature_canvas"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="#color/colorWhite" />
And last into your main activity :
public class MainActivity extends AppCompatActivity {
Button btnClear;
private CanvasView customCanvas;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
customCanvas = (CanvasView) findViewById(R.id.signature_canvas);
btnClear = (Button) findViewById(R.id.button1);
btnClear.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
customCanvas.clearCanvas(); // to clear canvas
}
});
}

i cannot draw a bitmap in android more than once even when my program draws lines multiple times which is included in the same block

i cannot draw a bitmap in android more than once even when my program draws lines multiple times which is included in the same block.
this is my code:
Bitmap cache,backup;
cache = Bitmap.createBitmap(480,800,paint);
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
backup = Bitmap.createBitmap(cache);
return true;
case MotionEvent.ACTION_MOVE:
canvas.drawLine(downX,downY,moveX,moveY,paint);
canvas.drawBitmap(backup,0,0,paint);
return true;
}
In your activity class
public class MyActivity extends Activity
{
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
MyView mv= new MyView(this);
setContentView(mv);
}
}
public class MyView extends View {
private Bitmap mBitmap;
private Canvas mCanvas;
private Paint mBitmapPaint;
private Paint mBitmapPaint;
Context mcontext;
public MyView(Context c) {
super(c);
mcontext=c;
mBitmapPaint = new Paint();
mBitmapPaint.setColor(Color.RED);//paint color set to red
}
// is called when your view is first assigned a size, and again if the size of your view changes for any reason.
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
//called everytime view is refreshed.
#Override
protected void onDraw(Canvas canvas) {
//do your draw here. draw lines and bitmaps.
Display display = ( (Activity) mcontext).getWindowManager().getDefaultDisplay();
float w = display.getWidth();
float h = display.getHeight();
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
//draw lines as border for the screen
canvas.drawLine(0, 0, w, 0,mBitmapPaint);
canvas.drawLine(0, 0, 0, h,mBitmapPaint);
canvas.drawLine(w,h,w,0,mBitmapPaint);
canvas.drawLine(w, h, 0,h , mBitmapPaint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();//refresh
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();//refresh
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();//refresh view
break;
}
return true;
}
private void touch_start(float x, float y) {
//do want should be done on touch start
}
private void touch_move(float x, float y) {
//do want should be done on touch move
}
private void touch_up() {
//do want should be done on touch up
}
}
Modify the above according to your needs.More information is available in the androdi developer site. http://developer.android.com/training/custom-views/custom-drawing.html

How do I draw an image from drawable onto an imageview with Canvas - Android

I have an activity which has an ImageView in it. What I want to do is be able to draw where the user touches that Imageview with an image from the drawable folder. I've read that the best way is to use Canvas, but I'm not sure where and how I integrate the onDraw method with the onTouchListener. This is what I have so far:
public class Main extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final TextView textView = (TextView)findViewById(R.id.textView);
final ImageView image = (ImageView) findViewById(R.id.imageView2);
//Bitmap
Bitmap viewBitmap = Bitmap.createBitmap(image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(viewBitmap);
image.draw(canvas);
image.setOnTouchListener(new View.OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
textView.setText("Touch coordinates : " + String.valueOf(event.getX()) + "x" + String.valueOf(event.getY()));
return false;
}
});
}
}
So what I want to do is when the user touches the ImageView, an image will be drawn exactly where he touched it.
You're going to want to subclass ImageView in order to override its onDraw() method. By doing so, you can also to the custom touch handling in onTouchEvent() instead of attaching a listener. This is not a complete example, but something like the following:
public class CustomImageView extends ImageView {
private ArrayList<Point) mTouches;
private Bitmap mMarker;
//Java constructor
public CustomImageView(Context context) {
super(context);
init();
}
//XML constructor
public CustomImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mTouches = new ArrayList<Point>();
mMarker = BitmapFactory.decodeResource(context.getResources(), R.drawable.my_marker_image);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
//Capture a reference to each touch for drawing
if(event.getAction() == MotionEvent.ACTION_DOWN) {
mTouches.add( new Point(event.getX(), event.getY()) );
return true;
}
return super.onTouchEvent(event);
}
#Override
protected void onDraw(Canvas c) {
//Let the image be drawn first
super.onDraw(c);
//Draw your custom points here
Paint paint = new Paint();
for(Point p : mTouches) {
c.drawBitmap(mMarker, p.x, p.y, paint);
}
}
}
HTH!
I edited your class like this and it works for me
public class MyImageView extends androidx.appcompat.widget.AppCompatImageView {
private Bitmap mMarker;
private Path mPath, circlePath ;
private Paint paint, circlePaint;
private Canvas mCanvas;
//Java constructor
public MyImageView(Context context) {
super(context);
init();
}
//XML constructor
public MyImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mTouches = new ArrayList<Point>();
paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeWidth(12);
mPath = new Path();
Paint mBitmapPaint = new Paint(Paint.DITHER_FLAG);
circlePaint = new Paint();
circlePath = new Path();
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeJoin(Paint.Join.MITER);
circlePaint.setStrokeWidth(4f);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mMarker = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mMarker);
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touch_move(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
mX = x;
mY = y;
circlePath.reset();
circlePath.addCircle(mX, mY, 30, Path.Direction.CW);
}
}
private void touch_up() {
mPath.lineTo(mX, mY);
circlePath.reset();
// commit the path to our offscreen
mCanvas.drawPath(mPath, paint);
// kill this so we don't double draw
mPath.reset();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
#Override
protected void onDraw(Canvas c) {
//Let the image be drawn first
super.onDraw(c);
c.drawBitmap(mMarker, 0, 0, paint);
c.drawPath( mPath, paint);
c.drawPath( circlePath, circlePaint);
}
}

How to make custom brush for canvas in android?

In my canvas application i want to use custom brushes like brushes in attached image.so please somebody help me fast how can i make custom brushes like attached image?
In my app i made doted line using following code:
mPaint.setPathEffect(new DashPathEffect(new float[] { 8, 8 }, 0));
and getting Blur and Emboss effect using following code:
mEmboss = new EmbossMaskFilter(new float[] { 1, 1, 1 }, 0.4f, 6, 3.5f);
mBlur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL);
As you can clearly see, no trivial shader effects / rectangles / circles can accomplish this.
Images / Bitmaps are used.
So simply repeatedly draw Bitmaps using canvas.drawBitmap. You draw the same Bitmap again and again while the finger moves.
For adding a custom color you can add a simple filter.
An Example
public class CanvasBrushDrawing extends View {
private Bitmap mBitmapBrush;
private Vector2 mBitmapBrushDimensions;
private List<Vector2> mPositions = new ArrayList<Vector2>(100);
private static final class Vector2 {
public Vector2(float x, float y) {
this.x = x;
this.y = y;
}
public final float x;
public final float y;
}
public CanvasBrushDrawing(Context context) {
super(context);
// load your brush here
mBitmapBrush = BitmapFactory.decodeResource(context.getResources(), R.drawable.splatter_brush);
mBitmapBrushDimensions = new Vector2(mBitmapBrush.getWidth(), mBitmapBrush.getHeight());
setBackgroundColor(0xffffffff);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (Vector2 pos : mPositions) {
canvas.drawBitmap(mBitmapBrush, pos.x, pos.y, null);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_MOVE:
final float posX = event.getX();
final float posY = event.getY();
mPositions.add(new Vector2(posX - mBitmapBrushDimensions.x / 2, posY - mBitmapBrushDimensions.y / 2));
invalidate();
}
return true;
}
}
Though it is too late i want to share something. This might help someone. Various brush techniques are discussed in the following link with JavaScript code for HTML canvas. All you have to do is convert JavaScript code to your expected one. It is pretty simple to covert JavaScript Canvas code to Android Canvas code.
Exploring canvas drawing techniques
I have converted "Multiple lines" technique to Java code for android; You can check the following android view code.
public class MultipleLines extends View {
private Bitmap bitmap;
private Canvas canvas;
private Paint mPaint;
public MultipleLines(Context context) {
super(context);
init();
}
private void init(){
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(0xFFFF0000);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(1);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
canvas = new Canvas(bitmap);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
private boolean isDrawing;
private List<PointF> points = new ArrayList<>();
private void touch_start(float touchX, float touchY) {
isDrawing = true;
points.add(new PointF(touchX, touchY));
canvas.save();
}
private void touch_move(float touchX, float touchY) {
if (!isDrawing) return;
canvas.drawColor(Color.TRANSPARENT);
points.add(new PointF(touchX, touchY));
stroke(offsetPoints(-10));
stroke(offsetPoints(-5));
stroke(points);
stroke(offsetPoints(5));
stroke(offsetPoints(10));
}
private void touch_up() {
isDrawing = false;
points.clear();
canvas.restore();
}
private List<PointF> offsetPoints(float val) {
List<PointF> offsetPoints = new ArrayList<>();
for (int i = 0; i < points.size(); i++) {
PointF point = points.get(i);
offsetPoints.add(new PointF(point.x + val, point.y + val));
}
return offsetPoints;
}
private void stroke(List<PointF> points) {
PointF p1 = points.get(0);
PointF p2 = points.get(1);
Path path = new Path();
path.moveTo(p1.x, p1.y);
for (int i = 1; i < points.size(); i++) {
// we pick the point between pi+1 & pi+2 as the
// end point and p1 as our control point
PointF midPoint = midPointBtw(p1, p2);
path.quadTo(p1.x, p1.y, midPoint.x, midPoint.y);
p1 = points.get(i);
if(i+1 < points.size()) p2 = points.get(i+1);
}
// Draw last line as a straight line while
// we wait for the next point to be able to calculate
// the bezier control point
path.lineTo(p1.x, p1.y);
canvas.drawPath(path,mPaint);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(bitmap, 0, 0, null);
}
private PointF midPointBtw(PointF p1, PointF p2) {
return new PointF(p1.x + (p2.x - p1.x) / 2.0f, p1.y + (p2.y - p1.y) / 2.0f);
}
}

Categories

Resources