ColorSpace Issues Migrating to PDFBox 2.0.x - pdfbox

Our department has inherited code that uses Apache PDFBox 1.8.x or earlier and we are in the process of trying to migrate it to Apache PDFBox 2.0.x.
I have resolved a lot of the various issues in this migration, but I'm still having problems migrating some of the ColorSpace related code. Below are some examples that I haven't figured out how to resolve. I've used the missing methods as the headings for each code snippet.
getColorSpaces() and setColorSpace()
public class ColorSpaceSetter extends OperatorProcessor {
private static final Logger logger = LogManager.getLogger(ColorSpaceSetter.class.getName());
public void process(Operator operator, List<COSBase> arguments) throws IOException {
try {
COSName arg = (COSName)arguments.get(0);
String argString = arg.getName();
if (context.getColorSpaces().containsKey(argString)) {
PDColorSpace colorSpace = context.getColorSpaces().get(argString);
if (colorSpace.getName().equals(COSName.SEPARATION.getName())) {
PDSeparation separation = (PDSeparation)colorSpace;
PDColor color;
//Non-stroking
if (StringUtils.isAllLowerCase(operator.getName())) {
color = context.getGraphicsState().getNonStrokingColor();
//Stroking
} else {
color = context.getGraphicsState().getStrokingColor();
}
color.setColorSpace(separation);
}
}
} catch (Exception e) {
logger.error("Unexpected argument array for operator " + operator.getName(), e);
}
}
}
getColorSpace()
public boolean determineStroking(PDColor color) {
for ( Float val : color.getColorSpace()) {
if (val != 1) {
return true;
}
}
return false;
}
setColorSpace() and setColorSpaceValue()
public class StrokeSetter extends OperatorProcessor {
public void process(Operator operator, List<COSBase> arguments) throws IOException {
//Supported operators are: g, rg, k, sc, and scn
//g = device gray (black or white)
//rg = rgb (000 is black, 111 is white, other is some other color)
//k = cmyk (0 is black, 1 is white, other is some other color)
//sc and scn = could be anything, but 0 is black, 1 is white)
boolean blackSeparation = false;
//Lowercase is non-stroking (fill) color
PDColor color;
if (StringUtils.isAllLowerCase(operator.getName())) {
color = context.getGraphicsState().getNonStrokingColor();
//Uppercase is stroking color
} else {
color = context.getGraphicsState().getStrokingColor();
}
//Treat separations differently - see section 4.5.5 of PDF Reference Documentation
PDColorSpace colorSpace = color.getColorSpace();
if (colorSpace.getName().equals(COSName.SEPARATION.getName())) {
PDSeparation separation = (PDSeparation)color.getColorSpace();
if (separation.getColorantName().equals("Black")) {
blackSeparation = true;
}
}
//Black and White
if (operator.getName().equalsIgnoreCase("g")) {
color.setColorSpace( new PDDeviceGray() );
float[] values = new float[1];
if ( arguments.size() >= 1 ) {
values[0] = ((COSNumber)arguments.get( 0 )).floatValue();
} else {
throw new IOException( "Error: Expected at least one argument when setting gray color");
}
color.setColorSpaceValue( values );
//RGB colors
} else if (operator.getName().equalsIgnoreCase("rg")) {
color.setColorSpace(PDDeviceRGB.INSTANCE);
float[] values = new float[3];
for ( int i = 0; i < arguments.size(); i++) {
values[i] = ((COSNumber)arguments.get( i )).floatValue();
}
color.setColorSpaceValue(values);
//CMYK colors
} else if (operator.getName().equalsIgnoreCase("k")) {
color.setColorSpace( PDDeviceCMYK.INSTANCE );
float[] values = new float[4];
for( int i=0; i<arguments.size(); i++ )
{
values[i] = ((COSNumber)arguments.get( i )).floatValue();
}
color.setColorSpaceValue(values);
// Unspecified ColorSpace
} else if (operator.getName().equalsIgnoreCase("sc") || operator.getName().equalsIgnoreCase("scn")) {
int size = arguments.size();
if ( size == 1) {
color.setColorSpace(new PDDeviceGray());
} else if ( size == 3) {
color.setColorSpace(PDDeviceRGB.INSTANCE);
} else if ( size == 4) {
color.setColorSpace(PDDeviceCMYK.INSTANCE);
} else {
color.setColorSpace(new PDDeviceN());
}
float[] values = new float[size];
for( int i=0; i<arguments.size(); i++ )
{
//Flip values when blackSeparation for PDDeviceGray
if (blackSeparation & size == 1) {
float val = ((COSNumber)arguments.get( i )).floatValue();
values[i] = Math.abs(val - 1);
} else {
values[i] = ((COSNumber)arguments.get( i )).floatValue();
}
}
color.setColorSpaceValue(values);
}
}
}

Related

JavaFx Problem with Service and Task with different Parameters and multiple calls

i need to create a Service and a Task to calculate the Mandelbrot and JuliaSet.
The calculation is working pretty good and now we need to give it into a Service and call it inside the task.
I have now the Problem, that every Time the task is executed, the Parameters are different.
I wrote a little Setter Function to parse those Arguments to the Service first.
But i'm not sure if this is the right Way?!
I'm also not sure how to correctly call the service in the main Function?
Now it works like this:
First time the service is executed, everything seems to work, but when i call it a secound Time, nothing seems to happen.....
Just to make sure: A Service can execute the Task multiple Times at the same Time?
Is it also posible with different Parameters?
Code Task:
private MandelbrotRenderOptions mandelbrot;
private JuliaRenderOptions juliaset;
private Canvas leftCanvas;
private Canvas rightCanvas;
//Constructor
public RenderTask(Canvas leftCanvas, Canvas rightCanvas) {
this.leftCanvas = leftCanvas;
this.rightCanvas = rightCanvas;
}
public void setOptions(MandelbrotRenderOptions mandelbrot, JuliaRenderOptions juliaset) {
this.mandelbrot = mandelbrot;
this.juliaset = juliaset;
}
#Override
protected Void call() throws Exception {
try {
System.out.println("HALLO SERVICE");
// instances for rendering the left canvas [pixel.data -> PixelWriter -> WritableImage -> GraphicsContext -> Canvas]
// creates an writable image which contains the dimensions of the canvas
WritableImage wimLeftCanvas = new WritableImage((int) leftCanvas.getWidth(), (int) leftCanvas.getHeight());
// instance which can write data into the image (instance above)
PixelWriter pwLeftCanvas = wimLeftCanvas.getPixelWriter();
// instance which fills the canvas
GraphicsContext gcLeftCanvas = leftCanvas.getGraphicsContext2D();
// instances for rendering the right canvas [pixel.data -> PixelWriter -> WritableImage -> GraphicsContext -> Canvas]
WritableImage wimRightCanvas = new WritableImage((int) rightCanvas.getWidth(), (int) rightCanvas.getHeight());
PixelWriter pwRight = wimRightCanvas.getPixelWriter();
GraphicsContext gcRightCanvas = rightCanvas.getGraphicsContext2D();
gcLeftCanvas.clearRect(0, 0, leftCanvas.getWidth(), leftCanvas.getHeight());
//Pixel[][] pixels; // contains pixel data for rendering canvas
// instances for logging the rendered data
SimpleImage simpleImageLeftCanvas = new SimpleImage((int) leftCanvas.getWidth(), (int) leftCanvas.getHeight());
SimpleImage simpleImageRightCanvas = new SimpleImage((int) rightCanvas.getWidth(), (int) rightCanvas.getHeight());
short dataSimpleImage[] = new short[3]; // contains pixel data for logging rendered data
// fills left canvas (mandelbrot) PixelWriter instance with data
Pixel[][] pixels = mandelbrot.setAllPixels();
FractalLogger.logRenderCall(mandelbrot);
for (int y = 0; y < (int) leftCanvas.getHeight(); y++) {
for (int x = 0; x < (int) leftCanvas.getWidth(); x++) {
// parses color data to PixelWriter instance
Color color = Color.rgb(pixels[y][x].getRed(), pixels[y][x].getGreen(), pixels[y][x].getBlue());
pwLeftCanvas.setColor(x, y, color);
for (int depth = 0; depth < 3; depth++) {
if (depth == 0) {
dataSimpleImage[depth] = pixels[y][x].getRed();
} else if (depth == 1) {
dataSimpleImage[depth] = pixels[y][x].getGreen();
} else {
dataSimpleImage[depth] = pixels[y][x].getBlue();
}
}
try {
simpleImageLeftCanvas.setPixel(x, y, dataSimpleImage); // because data must not be null
} catch (InvalidDepthException e) {
e.printStackTrace();
}
}
}
// logs that rendering of mandelbrot is finished
FractalLogger.logRenderFinished(FractalType.MANDELBROT, simpleImageLeftCanvas);
// fills left canvas (juliaset) PixelWriter instance with data
pixels = juliaset.setAllPixels();
FractalLogger.logRenderCall(mandelbrot);
for (int y = 0; y < (int) rightCanvas.getHeight(); y++) {
for (int x = 0; x < (int) rightCanvas.getWidth(); x++) {
// pareses color to PixelWriter instance
Color color = Color.rgb(pixels[y][x].getRed(), pixels[y][x].getGreen(), pixels[y][x].getBlue());
pwRight.setColor(x, y, color);
for (int depth = 0; depth < 3; depth++) {
if (depth == 0) {
dataSimpleImage[depth] = pixels[y][x].getRed();
} else if (depth == 1) {
dataSimpleImage[depth] = pixels[y][x].getGreen();
} else {
dataSimpleImage[depth] = pixels[y][x].getBlue();
}
}
try {
simpleImageRightCanvas.setPixel(x, y, dataSimpleImage); // because data must not be null
} catch (InvalidDepthException e) {
e.printStackTrace();
}
}
}
// logs that rendering of juliaset is finished
FractalLogger.logRenderFinished(FractalType.JULIA, simpleImageRightCanvas);
// writes data from WriteableImage instance to GraphicsContext instance, which finally parses renders it into the canvas
gcLeftCanvas.drawImage(wimLeftCanvas, 0, 0);
FractalLogger.logDrawDone(FractalType.MANDELBROT);
gcRightCanvas.drawImage(wimRightCanvas, 0, 0);
FractalLogger.logDrawDone(FractalType.JULIA);
return null;
} catch (Exception e) {
System.out.println("ERROR");
System.out.println(e);
return null;
}
}
#Override
protected void cancelled()
{
super.cancelled();
updateMessage("The task was cancelled.");
}
#Override
protected void failed()
{
super.failed();
updateMessage("The task failed.");
}
#Override
public void succeeded()
{
super.succeeded();
updateMessage("The task finished successfully.");
} ```
And i call it like this in the main:
``` Service service = new Service() {
#Override
protected Task createTask() {
return new RenderTask(leftCanvas, rightCanvas);
}
};
task.setOptions(mandelbrot, juliaset);
service.restart(); ```

How to put different limit for multi chekbox in recyclerview item

I can choose 2 items from the first group and choose 1 item from the second group.
Now there should be a certain limit for each group and the whole choice as well.
How can I apply it?
#Override
public void onBindViewHolder(#NonNull Holder holder, int position) {
holder.txt_ingredient.setText(ingredients.get(position).getName());
ArrayList<HomeList.Ingredient> sizeArrayList = new ArrayList<>();
sizeArrayList.addAll(ingredients);
for (int i = 0; i < ingredients.get(position).getIngredients().size(); i++) {
indi.add(ingredients.get(position).getIngredients().get(i).getId());
}
for (int i = 0; i < sizeArrayList.get(position).getIngredients().size(); i++) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View rowView = inflater.inflate(R.layout.checkbox_feild, null);
holder.parentLinearSize.addView(rowView, holder.parentLinearSize.getChildCount() - 1);
}
for (int itemPos = 0; itemPos < holder.parentLinearSize.getChildCount(); itemPos++) {
View view1 = holder.parentLinearSize.getChildAt(itemPos);
CheckBox ch = (CheckBox) view1.findViewById(R.id.chkSpe);
TextView cat_value = (TextView) view1.findViewById(R.id.cat_value);
String c = String.valueOf(sizeArrayList.get(position).getIngredients().size());
ch.setText(sizeArrayList.get(position).getIngredients().get(itemPos).getTitle());
ch.setOnCheckedChangeListener(null);
int finalItemPos = itemPos;
ch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
int limit = Integer.parseInt(sizeArrayList.get(position).getSelectionLimit());
int globalInc = 0;
if (globalInc == limit && isChecked) {
ch.setChecked(false);
Toast.makeText(context,
"Limit reached!!!", Toast.LENGTH_SHORT).show();
} else if (isChecked) {
globalInc++;
Toast.makeText(context,
globalInc + " checked!",
Toast.LENGTH_SHORT)
.show();
ch.setSelected(isChecked);
if (ch.isChecked()) {
for (int i = 0; i < ingredients.get(position).getIngredients().size(); i++) {
if (i == finalItemPos) {
ingredients.get(position).getIngredients().get(i).setQty("1");
} else
ingredients.get(position).getIngredients().get(i).setQty("0");
}
ingredients.get(position).setIsOpenSection("1");
onItemCheckListener.onItemCheck(sizeArrayList.get(position).getIngredients(), sizeArrayList.get(position));
Toast.makeText(context, sizeArrayList.get(position).getIngredients().get(finalItemPos).getPrice(), Toast.LENGTH_SHORT).show();
onRecycleItemClickListenerExtra.onItemClickListener(holder, position, "selectExtra", sizeArrayList.get(position).getIngredients().get(finalItemPos).getPrice(), "trextra");
} else {
onItemCheckListener.onItemUncheck(sizeArrayList.get(position).getIngredients().get(position));
onRecycleItemClickListenerExtra.onItemClickListener(holder, position, "DeselectExtra", sizeArrayList.get(position).getIngredients().get(finalItemPos).getPrice(), "trextra");
sizeArrayList.get(position).getIngredients().get(finalItemPos).setQty("0");
}
} else if (!isChecked) {
globalInc--;
}
}
});
cat_value.setText(sizeArrayList.get(position).getIngredients().get(itemPos).getPrice());
holder.maximum_amt.setText(sizeArrayList.get(position).getMaximumAmount());
holder.select_limit.setText(sizeArrayList.get(position).getSelectionLimit());
String count = String.valueOf(getItemCount());
holder.total_itm_count.setText(c);
String eql_les_grt = sizeArrayList.get(position).getEqualGraterLess();
if (eql_les_grt.equalsIgnoreCase("1")) {
if (lan.equals("English")) {
String eql_ls_status = "Greater";
holder.euql_grt_les.setText(eql_ls_status);
}
if (lan.equals("Español")) {
String eql_ls_status = "Máximo";
holder.euql_grt_les.setText(eql_ls_status);
}
}
if (eql_les_grt.equalsIgnoreCase("2")) {
if (lan.equals("English")) {
String eql_ls_status = "Exactly";
holder.euql_grt_les.setText(eql_ls_status);
}
if (lan.equals("Español")) {
String eql_ls_status = "solo";
holder.euql_grt_les.setText(eql_ls_status);
}
}
if (eql_les_grt.equalsIgnoreCase("3")) {
if (lan.equals("English")) {
String eql_ls_status = "Less";
holder.euql_grt_les.setText(eql_ls_status);
}
if (lan.equals("Español")) {
String eql_ls_status = "Mínimo";
holder.euql_grt_les.setText(eql_ls_status);
}
}
holder.img_arrow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.rl_details.setVisibility(View.VISIBLE);
holder.img_dwn_arrow.setVisibility(View.VISIBLE);
holder.img_dwn_arrow.setVisibility(View.VISIBLE);
holder.img_arrow.setVisibility(View.GONE);
holder.parentLinearSize.setVisibility(View.VISIBLE);
}
});
holder.img_dwn_arrow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.rl_details.setVisibility(View.GONE);
holder.img_dwn_arrow.setVisibility(View.GONE);
holder.img_dwn_arrow.setVisibility(View.GONE);
holder.img_arrow.setVisibility(View.VISIBLE);
holder.parentLinearSize.setVisibility(View.GONE);
}
});
}

Adjust Brightness, Contrast using Camera.Parameters

I were trying to make a camera application, I'm unable to find a way to change camera brightness, contrast using Camera.Parameters
So my question is how to add Brightness and contrast feature to increase/decrease brightness/contrast. For example if I increase the seekbarit increase the brightness. if I decrease the seekbar it decrease the brightness.
Please edit my code or put your seprate answer to help me.
package com.example.beautymaker;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.hardware.Camera;
import android.hardware.camera2.CameraCharacteristics;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import com.zomato.photofilters.imageprocessors.Filter;
import com.zomato.photofilters.imageprocessors.subfilters.BrightnessSubFilter;
import java.io.IOException;
import java.util.List;
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
mHolder = getHolder();
mHolder.addCallback(this);
/*Camera.Parameters params = camera.getParameters();
final int[] previewFpsRange = new int[2];
params.getPreviewFpsRange(previewFpsRange);
if (previewFpsRange[0] == previewFpsRange[1]) {
final List<int[]> supportedFpsRanges = params.getSupportedPreviewFpsRange();
for (int[] range : supportedFpsRanges) {
if (range[0] != range[1]) {
params.setPreviewFpsRange(range[0], range[1]);
break;
}
}
}*/
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
try {
// create the surface and start camera preview
if (mCamera == null) {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
}
} catch (IOException e) {
Log.d(VIEW_LOG_TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void refreshCamera(Camera camera) {
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
setCamera;
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.d(VIEW_LOG_TAG, "Error starting camera preview: " + e.getMessage());
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
refreshCamera(mCamera);
}
public void setCamera(Camera camera) {
//method to set a camera instance
mCamera = camera;
Camera.Parameters parameters = mCamera.getParameters();
// parameters.setPreviewFpsRange(1500,3000);
parameters.setExposureCompensation(parameters.getMaxExposureCompensation());
if(parameters.isAutoExposureLockSupported())
{
parameters.setAutoExposureLock(false);
}
// parameters.setColorEffect(Camera.Parameters.WHITE_BALANCE_INCANDESCENT);
parameters.getAutoExposureLock();
parameters.set("iso",50);
// parameters.setWhiteBalance();
parameters.setAutoWhiteBalanceLock(true);
parameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_SHADE);
/*Filter filter = new Filter();
filter.addSubFilter(new BrightnessSubFilter(parameters));*/
mCamera.setParameters(parameters);
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
// mCamera.release();
}
//for brightness
public static Bitmap doBrightness(Bitmap src, int value) {
// image size
int width = src.getWidth();
int height = src.getHeight();
// create output bitmap
Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
// color information
int A, R, G, B;
int pixel;
// scan through all pixels
for(int x = 0; x < width; ++x) {
for(int y = 0; y < height; ++y) {
// get pixel color
pixel = src.getPixel(x, y);
A = Color.alpha(pixel);
R = Color.red(pixel);
G = Color.green(pixel);
B = Color.blue(pixel);
// increase/decrease each channel
R += value;
if(R > 255) { R = 255; }
else if(R < 0) { R = 0; }
G += value;
if(G > 255) { G = 255; }
else if(G < 0) { G = 0; }
B += value;
if(B > 255) { B = 255; }
else if(B < 0) { B = 0; }
// apply new pixel color to output bitmap
bmOut.setPixel(x, y, Color.argb(A, R, G, B));
}
}
// return final image
return bmOut;
}
}
there is no method in Camera.Parameters to achieve this. You have to read this documentation for this class to check the available parameters and this class is deprecated in API 21 and above.

How to set both axis's scales to be always the same?

MPAndroidChart allows you to zoom in the X axis, Y axis and both. I would like to rescale the remaining axis (or both) to match the one(s) being scaled.
For that I've created a OnChartGestureListener:
public class ZoomNotDistorting implements OnChartGestureListener {
private Chart chart;
private ViewPortHandler viewPortHandler;
private float startDist = 1f;
private float scaleX, scaleY;
public ZoomNotDistorting(Chart chart) {
this.chart = chart;
this.viewPortHandler = chart.getViewPortHandler();
}
#Override
public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {
int action = me.getAction() & MotionEvent.ACTION_MASK;
if(action == MotionEvent.ACTION_POINTER_DOWN && me.getPointerCount() >= 2) {
startDist = spacing(me);
}
}
#Override
public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {
switch (lastPerformedGesture) {
case PINCH_ZOOM:
float scale = spacing(me) / startDist; // total scale
boolean isZoomingOut = (scale < 1);
if(isZoomingOut) {
if(scaleX < scaleY) {
viewPortHandler.zoom(scaleX, scaleX);
} else {
viewPortHandler.zoom(scaleY, scaleY);
}
} else {
if(scaleX > scaleY) {
viewPortHandler.zoom(scaleX, scaleX);
} else {
viewPortHandler.zoom(scaleY, scaleY);
}
}
break;
case X_ZOOM:
viewPortHandler.zoom(scaleX, scaleX);
break;
case Y_ZOOM:
viewPortHandler.zoom(scaleY, scaleY);
break;
}
chart.invalidate();
}
#Override
public void onChartLongPressed(MotionEvent me) {}
#Override
public void onChartDoubleTapped(MotionEvent me) {}
#Override
public void onChartSingleTapped(MotionEvent me) {}
#Override
public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) {}
#Override
public void onChartScale(MotionEvent me, float scaleX, float scaleY) {
this.scaleX = scaleX;
this.scaleY = scaleY;
}
#Override
public void onChartTranslate(MotionEvent me, float dX, float dY) {}
/**
* returns the distance between two pointer touch points
*/
private static float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return (float) Math.sqrt(x * x + y * y);
}
}
That class doesn't seem to be doing anything,How to set both axis's scales to be always the same?
Also, here is my chart class:
public class MathGraph extends LineChart {
public static final int BOUNDARIES = 100;
public static final int DATA_POINTS = 200;
private static final int LINE_WIDTH = 2;
private LineData data;
public MathGraph(Context context, AttributeSet attrs) {
super(context, attrs);
super.setDescription(null);
//Misc
getLegend().setEnabled(false);
setRenderer(new LineChatRendererNoData(this, mAnimator, mViewPortHandler));
//Lines encasing the chart
getXAxis().setAxisLineWidth(LINE_WIDTH);
getAxisLeft().setAxisLineWidth(LINE_WIDTH);
getAxisRight().setEnabled(false);
//Line for (x; 0)
getAxisLeft().setDrawZeroLine(true);
getAxisLeft().setZeroLineWidth(LINE_WIDTH);
getAxisRight().setDrawZeroLine(true);
getAxisRight().setZeroLineWidth(LINE_WIDTH);
//Line for (0; y)
LimitLine limitLine = new LimitLine(0f);
limitLine.setLineColor(Color.GRAY);
limitLine.setLineWidth(LINE_WIDTH);
getXAxis().addLimitLine(limitLine);
setOnChartGestureListener(new ZoomNotDistorting(this));
}
public void setFunction(Function f) {
if(!f.checkSyntax()) throw new IllegalStateException("Error in function: " + f.toString() + "!");
setDescription(f);
data = null;
LoadFunctionAsyncTask l = new LoadFunctionAsyncTask(f, -BOUNDARIES, BOUNDARIES, DATA_POINTS,
(List<Entry> pointList) -> {
if(data == null) {
ILineDataSet dataSet = new LineDataSet(new ArrayList<>(), null);
dataSet.setValueFormatter(new PointValueFormatter());
dataSet.setHighlightEnabled(true);
for (Entry dataPoint : pointList) {
dataSet.addEntry(dataPoint);
}
data = new LineData(dataSet);
setData(data);
} else {
for (Entry dataPoint : pointList) {
data.addEntry(dataPoint, 0);// 0 is the only dataset
}
data.notifyDataChanged();
notifyDataSetChanged();
invalidate();
}
});
l.execute();
}
private void setDescription(Function f) {
Description desc = new Description();
desc.setText(f.getDescription());
desc.setPosition(16, getBottom() - 16);
setDescription(desc);
}
private class PointValueFormatter implements IValueFormatter {
#Override
public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {
return "(" + entry.getX() + ", " + entry.getY() + ")";
}
}
}
OK, apparently chart.invalidate() isn't enough, the Matrix needs to be refreshed:
Matrix matrix = null;
//...
matrix = viewPortHandler.zoom(scaleX, scaleX);
//...
if(matrix != null) {
viewPortHandler.refresh(matrix, chart, true);
}
As a bonus, the last true in refresh() is for invalidate, so no need for chart.invalidate();.

Color change a background in processing w/ out affecting particles

I'm trying to fade a background in and out into different colors. I decided to try drawing a rect rather than using background, but I'm getting trails on my particles, because the background isn't getting drawn. Suggestions on how to fix this?
// main tab
ArrayList<ParticleSystem> systems;
PVector windRight = new PVector(0.1,0);
PVector sortaSpeed = new PVector(-0.1,0);
PVector gravity = new PVector(0,0.05);
boolean wR = false;
boolean sP = false;
boolean cS = false;
int limit = 8;
int alpha = 10;
color[] colorArray = {color(0,0,0,alpha),color(16, 37, 43,alpha),color(51, 10, 10,alpha),color(126, 255, 0,alpha)};
int currentColor;
int nextColor;
boolean change = false;
void setup() {
size(640,480);
systems = new ArrayList<ParticleSystem>();
smooth();
noStroke();
currentColor = 0;
for(int i = 0; i < limit; i++){
systems.add(new ParticleSystem(random(100,200),10,new PVector(random(100,500),-5))); //random(480)
}
background(0);
}
void draw() {
//rect(0, 0, 2000, 2000);
fill(colorArray[currentColor]);
rect(0, 0, width*2, height*2);
//background(colorArray[currentColor]);
if(change){
currentColor = nextColor;
change = false;
}
if(!systems.isEmpty()){
for (int i =0; i < systems.size(); i++){
ParticleSystem ps = systems.get(i);
ps.applyForce(gravity);
ps.run();
if(wR){
ps.applyForce(windRight);
}
if(sP){
ps.applyForce(sortaSpeed);
}
}
}
}
void keyPressed() {
if(key == 'w'){
wR = true;
print("w");
}
if(key == 'a'){
print('a');
sP = true;
}
}
void keyReleased(){
if(key == 'w'){
wR = false;
} else if(key == 'a'){
sP = false;
} else if(key == 's'){
if(key == 's'){
change = true;
println("currentColor: "+currentColor);
int newColor = currentColor;
while (newColor == currentColor)
newColor=(int) random(colorArray.length);
nextColor = newColor;
}
} // end of cS
}
In the future, please try to post an MCVE. Right now we can't run your code because it contains compiler errors. We don't need to see your entire sketch anyway though, just a small example that gets the point across.
But your problem is caused because you're trying to use alpha values in your background. That won't work with the background() function because that function ignores alpha values, and it won't work with the rect() function because then you won't be clearing out old frames- you'll see them through the transparent rectangle.
Instead, you could use the lerpColor() function to calculate the transition from one color to another over time.
Here's an example that transitions between random colors:
color fromColor = getRandomColor();
color toColor = getRandomColor();
float currentLerpValue = 0;
float lerpStep = .01;
void draw() {
color currentColor = lerpColor(fromColor, toColor, currentLerpValue);
currentLerpValue += lerpStep;
if (currentLerpValue >= 1) {
fromColor = currentColor;
toColor= getRandomColor();
currentLerpValue = 0;
}
background(currentColor);
}
color getRandomColor() {
return color(random(255), random(255), random(255));
}