jjzjj

android - 如何在android中裁剪图像

coder 2023-11-26 原文

我正在 android 中创建应用程序。在这个应用程序中有裁剪图像的一部分。 当我用谷歌搜索时,我得到了一些基于图像裁剪的想法,但我在那里遇到了一些问题,因为我有一张人像。在这里我需要准确裁剪人的脸,但我的代码只适用于矩形并覆盖 sdcard 中的图像。 我对该代码感到困惑..任何人都可以帮助我......

编辑:

 super.onCreate(icicle);
mContentResolver = getContentResolver();

requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.cropimage);

mImageView = (CropImageView) findViewById(R.id.image);

showStorageToast(this);

Intent intent = getIntent();
Bundle extras = intent.getExtras();
if (extras != null) {
    if (extras.getString("circleCrop") != null) {
    mCircleCrop = true;
    mAspectX = 1;
    mAspectY = 1;
    }

    mImagePath = extras.getString("image-path");

    mSaveUri = getImageUri(mImagePath);
    mBitmap = getBitmap(mImagePath);

    mAspectX = extras.getInt("aspectX");
    mAspectY = extras.getInt("aspectY");
    mOutputX = extras.getInt("outputX");
    mOutputY = extras.getInt("outputY");
    mScale = extras.getBoolean("scale", true);
    mScaleUp = extras.getBoolean("scaleUpIfNeeded", true);
}



if (mBitmap == null) {
    Log.d(TAG, "finish!!!");
    finish();
    return;
}

// Make UI fullscreen.
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

findViewById(R.id.discard).setOnClickListener(
    new View.OnClickListener() {
        public void onClick(View v) {
        setResult(RESULT_CANCELED);
        finish();
        }
    });

findViewById(R.id.save).setOnClickListener(
    new View.OnClickListener() {
        public void onClick(View v) {
        onSaveClicked();
        }
    });
startFaceDetection();
}

private Uri getImageUri(String path) {
return Uri.fromFile(new File(path));
}

private Bitmap getBitmap(String path) {
Uri uri = getImageUri(path);
InputStream in = null;
try {
    in = mContentResolver.openInputStream(uri);
    return BitmapFactory.decodeStream(in);
} catch (FileNotFoundException e) {
    Log.e(TAG, "file " + path + " not found");
}
return null;
}


private void startFaceDetection() {
if (isFinishing()) {
    Toast.makeText(this, "Inside Face Detection",Toast.LENGTH_LONG).show();
    return;
}
Toast.makeText(this, "Outside Face Detection",Toast.LENGTH_LONG).show();
mImageView.setImageBitmapResetBase(mBitmap, true);


Util.startBackgroundJob(this, null,
    "Please wait\u2026",
    new Runnable() {
    public void run() {

    final CountDownLatch latch = new CountDownLatch(1);
    final Bitmap b = (mImage != null)
    ? mImage.fullSizeBitmap(IImage.UNCONSTRAINED,
        1024 * 1024)
        : mBitmap;
    mHandler.post(new Runnable() {
        public void run() {
        if (b != mBitmap && b != null) {
            mImageView.setImageBitmapResetBase(b, true);
          //  mBitmap.recycle();
            mBitmap = b;
        }
        if (mImageView.getScale() == 1F) {
            mImageView.center(true, true);
        }
        latch.countDown();
        }
    });
    try {
        latch.await();
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
    mRunFaceDetection.run();
    }
}, mHandler);
}



private void onSaveClicked() {
// TODO this code needs to change to use the decode/crop/encode single
// step api so that we don't require that the whole (possibly large)
// bitmap doesn't have to be read into memory
if (mSaving) return;

if (mCrop == null) {
    return;
}

mSaving = true;

Rect r = mCrop.getCropRect();

int width = (int) r.width();
int height = (int) r.height();

// If we are circle cropping, we want alpha channel, which is the
// third param here.
Bitmap croppedImage = Bitmap.createBitmap(width, height,
    mCircleCrop
    ? Bitmap.Config.ARGB_8888
        : Bitmap.Config.RGB_565);
{
    Canvas canvas = new Canvas(croppedImage);
    RectF dstRect = new RectF(0, 0, width, height);
   // canvas.drawBitmap(mBitmap, r, dstRect, null);
   // canvas.drawOval(dstRect, null);

   canvas.drawBitmap(mBitmap, r, dstRect, null);
}

if (mCircleCrop) {
    // OK, so what's all this about?
    // Bitmaps are inherently rectangular but we want to return
    // something that's basically a circle.  So we fill in the
    // area around the circle with alpha.  Note the all important
    // PortDuff.Mode.CLEAR.
    Canvas c = new Canvas(croppedImage);
    Path p = new Path();
    p.addCircle(width / 2F, height / 2F, width / 2F,
        Path.Direction.CW);
    c.clipPath(p, Region.Op.DIFFERENCE);
    c.drawColor(0x00000000, PorterDuff.Mode.CLEAR);
}

/* If the output is required to a specific size then scale or fill */
if (mOutputX != 0 && mOutputY != 0) {
    if (mScale) {
    /* Scale the image to the required dimensions */
    Bitmap old = croppedImage;
    croppedImage = Util.transform(new Matrix(),
        croppedImage, mOutputX, mOutputY, mScaleUp);
    if (old != croppedImage) {
        old.recycle();
    }
    } else {

    /* Don't scale the image crop it to the size requested.
     * Create an new image with the cropped image in the center and
     * the extra space filled.
     */

    // Don't scale the image but instead fill it so it's the
    // required dimension
    Bitmap b = Bitmap.createBitmap(mOutputX, mOutputY,
        Bitmap.Config.RGB_565);
    Canvas canvas = new Canvas(b);

    Rect srcRect = mCrop.getCropRect();
    RectF dstRect = new RectF(0, 0, mOutputX, mOutputY);

    int dx = (int) ((srcRect.width() - dstRect.width()) / 2);
    int dy = (int) ((srcRect.height() - dstRect.height()) / 2);

    /* If the srcRect is too big, use the center part of it. */
    srcRect.inset(Math.max(0, dx), Math.max(0, dy));

    /* If the dstRect is too big, use the center part of it. */
    dstRect.inset(Math.max(0, -dx), Math.max(0, -dy));

    /* Draw the cropped bitmap in the center */
    //canvas.drawBitmap(mBitmap, srcRect, dstRect, null);
    canvas.drawOval(dstRect, null);

    /* Set the cropped bitmap as the new bitmap */
    croppedImage.recycle();
    //croppedImage = b;
    }
}

// Return the cropped image directly or save it to the specified URI.
Bundle myExtras = getIntent().getExtras();
//if (myExtras != null && (myExtras.getParcelable("data") != null
//    || myExtras.getBoolean("return-data"))) {
    Bundle extras = new Bundle(); 
    extras.putParcelable("data", croppedImage);
   Intent intent=new Intent(CropImage.this,nextImage.class); 
   intent.putExtras(extras);
   startActivity(intent);
    //setResult(RESULT_OK,
      //  (new Intent()).setAction("inline-daintentta").putExtras(extras));
   // finish();
//} 
/*else {
    final Bitmap b = croppedImage;
    Util.startBackgroundJob(this, null,"Saving image",
        new Runnable() {
    public void run() {
        saveOutput(b);
    }
    }, mHandler);
}*/
}

private void saveOutput(Bitmap croppedImage) {
if (mSaveUri != null) {
    OutputStream outputStream = null;
    try {
    outputStream = mContentResolver.openOutputStream(mSaveUri);
    if (outputStream != null) {
        croppedImage.compress(mOutputFormat, 75, outputStream);
    }
    } catch (IOException ex) {
    // TODO: report error to caller
    Log.e(TAG, "Cannot open file: " + mSaveUri, ex);
    } finally {
    Util.closeSilently(outputStream);
    }
    Bundle extras = new Bundle();
    setResult(RESULT_OK, new Intent(mSaveUri.toString())
    .putExtras(extras));
} else {
    Log.e(TAG, "neni definovana adresa pro ulozeni");
    /*Bundle extras = new Bundle();
    extras.putString("rect", mCrop.getCropRect().toString());

    File oldPath = new File(mImage.getDataPath());
    File directory = new File(oldPath.getParent());

    int x = 0;
    String fileName = oldPath.getName();
    fileName = fileName.substring(0, fileName.lastIndexOf("."));

    // Try file-1.jpg, file-2.jpg, ... until we find a filename which
    // does not exist yet.
    while (true) {
    x += 1;
    String candidate = directory.toString()
    + "/" + fileName + "-" + x + ".jpg";
    boolean exists = (new File(candidate)).exists();
    if (!exists) {
        break;
    }
    }

    try {
    Uri newUri = ImageManager.addImage(
        mContentResolver,
        mImage.getTitle(),
        mImage.getDateTaken(),
        null,    // TODO this null is going to cause us to lose
        // the location (gps).
        0,       // TODO this is going to cause the orientation
        // to reset.
        directory.toString(),
        fileName + "-" + x + ".jpg");

     Cancelable<Void> cancelable =
                    ImageManager.storeImage(
                    newUri,
                    mContentResolver,
                    0, // TODO fix this orientation
                    croppedImage,
                    null);

            cancelable.get();
    setResult(RESULT_OK, new Intent()
    .setAction(newUri.toString())
    .putExtras(extras));
    } catch (Exception ex) {
    // basically ignore this or put up
    // some ui saying we failed
    Log.e(TAG, "store image fail, continue anyway", ex);
    }
    */
}
//croppedImage.recycle();
finish();
}

@Override
protected void onPause() {
super.onPause();
BitmapManager.instance().cancelThreadDecoding(mDecodingThreads);
    //mBitmap.recycle();
}

@Override
protected void onDestroy() {
super.onDestroy();
}


Runnable mRunFaceDetection = new Runnable() {
@SuppressWarnings("hiding")
float mScale = 1F;
Matrix mImageMatrix;
FaceDetector.Face[] mFaces = new FaceDetector.Face[3];
int mNumFaces;

// For each face, we create a HightlightView for it.
private void handleFace(FaceDetector.Face f) {
    PointF midPoint = new PointF();

    int r = ((int) (f.eyesDistance() * mScale)) * 2;
    f.getMidPoint(midPoint);
    midPoint.x *= mScale;
    midPoint.y *= mScale;

    int midX = (int) midPoint.x;
    int midY = (int) midPoint.y;

    HighlightView hv = new HighlightView(mImageView);

    int width = mBitmap.getWidth();
    int height = mBitmap.getHeight();

    RectF imageRect = new RectF(0, 0, width, height);

    RectF faceRect = new RectF(midX, midY, midX, midY);
    faceRect.inset(-r, -r);
    if (faceRect.left < 0) {
    faceRect.inset(-faceRect.left, -faceRect.left);
    }

    if (faceRect.top < 0) {
    faceRect.inset(-faceRect.top, -faceRect.top);
    }

    if (faceRect.right > imageRect.right) {
    faceRect.inset(faceRect.right - imageRect.right,
        faceRect.right - imageRect.right);
    }

    if (faceRect.bottom > imageRect.bottom) {
    faceRect.inset(faceRect.bottom - imageRect.bottom,
        faceRect.bottom - imageRect.bottom);
    }

    hv.setup(mImageMatrix, imageRect, faceRect, mCircleCrop,
        mAspectX != 0 && mAspectY != 0);

    mImageView.add(hv);
}

// Create a default HightlightView if we found no face in the picture.
private void makeDefault() {
    HighlightView hv = new HighlightView(mImageView);

    int width = mBitmap.getWidth();
    int height = mBitmap.getHeight();

    RectF imageRect = new RectF(0, 0, width, height);

    // make the default size about 4/5 of the width or height
    int cropWidth = Math.min(width, height) * 4 / 5;
    int cropHeight = cropWidth;

    if (mAspectX != 0 && mAspectY != 0) {
    if (mAspectX > mAspectY) {
        cropHeight = cropWidth * mAspectY / mAspectX;
    } else {
        cropWidth = cropHeight * mAspectX / mAspectY;
    }
    }

    int x = (width - cropWidth) / 2;
    int y = (height - cropHeight) / 2;

    RectF cropRect = new RectF(x, y, x + cropWidth, y + cropHeight);
    hv.setup(mImageMatrix, imageRect, cropRect, mCircleCrop,
        mAspectX != 0 && mAspectY != 0);
    mImageView.add(hv);
}

// Scale the image down for faster face detection.
private Bitmap prepareBitmap() {
    if (mBitmap == null) {
    return null;
    }

    // 256 pixels wide is enough.
    if (mBitmap.getWidth() > 256) {
    mScale = 256.0F / mBitmap.getWidth();
    }
    Matrix matrix = new Matrix();
    matrix.setScale(mScale, mScale);
    Bitmap faceBitmap = Bitmap.createBitmap(mBitmap, 0, 0, mBitmap
        .getWidth(), mBitmap.getHeight(), matrix, true);
    return faceBitmap;
}

public void run() {
    mImageMatrix = mImageView.getImageMatrix();
    Bitmap faceBitmap = prepareBitmap();

    mScale = 1.0F / mScale;
    if (faceBitmap != null && mDoFaceDetection) {
    FaceDetector detector = new FaceDetector(faceBitmap.getWidth(),
        faceBitmap.getHeight(), mFaces.length);
    mNumFaces = detector.findFaces(faceBitmap, mFaces);
    }

    if (faceBitmap != null && faceBitmap != mBitmap) {
//    faceBitmap.recycle();
    }

    mHandler.post(new Runnable() {
    public void run() {
        mWaitingToPick = mNumFaces > 1;
        if (mNumFaces > 0) {
        for (int i = 0; i < mNumFaces; i++) {
            handleFace(mFaces[i]);
        }
        } else {
        makeDefault();
        }
        mImageView.invalidate();
        if (mImageView.mHighlightViews.size() == 1) {
        mCrop = mImageView.mHighlightViews.get(0);
        mCrop.setFocus(true);
        }

        if (mNumFaces > 1) {
        Toast t = Toast.makeText(CropImage.this,
            "Multi face crop help",
            Toast.LENGTH_SHORT);
        t.show();
        }
    }
    });
}
};

public static final int NO_STORAGE_ERROR = -1;
public static final int CANNOT_STAT_ERROR = -2;

public static void showStorageToast(Activity activity) {
showStorageToast(activity, calculatePicturesRemaining());
}

public static void showStorageToast(Activity activity, int remaining) {
String noStorageText = null;

if (remaining == NO_STORAGE_ERROR) {
    String state = Environment.getExternalStorageState();
    if (state == Environment.MEDIA_CHECKING) {
    noStorageText = "Preparing card";
    } else {
    noStorageText = "No storage card";
    }
} else if (remaining < 1) {
    noStorageText = "Not enough space";
}

if (noStorageText != null) {
    Toast.makeText(activity, noStorageText, 5000).show();
}
}

public static int calculatePicturesRemaining() {
try {
    /*if (!ImageManager.hasStorage()) {
            return NO_STORAGE_ERROR;
        } else {*/
    String storageDirectory =
    Environment.getExternalStorageDirectory().toString();
    StatFs stat = new StatFs(storageDirectory);
    float remaining = ((float) stat.getAvailableBlocks()
        * (float) stat.getBlockSize()) / 400000F;
    return (int) remaining;
    //}
} catch (Exception ex) {
    // if we can't stat the filesystem then we don't know how many
    // pictures are remaining.  it might be zero but just leave it
    // blank since we really don't know.
    return CANNOT_STAT_ERROR;
}
}



 }


class CropImageView extends ImageViewTouchBase {
ArrayList<HighlightView> mHighlightViews = new ArrayList<HighlightView>();
HighlightView mMotionHighlightView = null;
float mLastX, mLastY;
int mMotionEdge;

private Context mContext;

@Override
protected void onLayout(boolean changed, int left, int top,
    int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (mBitmapDisplayed.getBitmap() != null) {
    for (HighlightView hv : mHighlightViews) {
    hv.mMatrix.set(getImageMatrix());
    hv.invalidate();
    if (hv.mIsFocused) {
        centerBasedOnHighlightView(hv);
    }
    }
}
}

public CropImageView(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
}

@Override
protected void zoomTo(float scale, float centerX, float centerY) {
super.zoomTo(scale, centerX, centerY);
for (HighlightView hv : mHighlightViews) {
    hv.mMatrix.set(getImageMatrix());
    hv.invalidate();
}
}

@Override
protected void zoomIn() {
super.zoomIn();
for (HighlightView hv : mHighlightViews) {
    hv.mMatrix.set(getImageMatrix());
    hv.invalidate();
}
}

@Override
protected void zoomOut() {
super.zoomOut();
for (HighlightView hv : mHighlightViews) {
    hv.mMatrix.set(getImageMatrix());
    hv.invalidate();
}
}

@Override
protected void postTranslate(float deltaX, float deltaY) {
super.postTranslate(deltaX, deltaY);
for (int i = 0; i < mHighlightViews.size(); i++) {
    HighlightView hv = mHighlightViews.get(i);
    hv.mMatrix.postTranslate(deltaX, deltaY);
    hv.invalidate();
}
}

// According to the event's position, change the focus to the first
// hitting cropping rectangle.
private void recomputeFocus(MotionEvent event) {
for (int i = 0; i < mHighlightViews.size(); i++) {
    HighlightView hv = mHighlightViews.get(i);
    hv.setFocus(false);
    hv.invalidate();
}

for (int i = 0; i < mHighlightViews.size(); i++) {
    HighlightView hv = mHighlightViews.get(i);
    int edge = hv.getHit(event.getX(), event.getY());
    if (edge != HighlightView.GROW_NONE) {
    if (!hv.hasFocus()) {
        hv.setFocus(true);
        hv.invalidate();
    }
    break;
    }
}
invalidate();
}

@Override
public boolean onTouchEvent(MotionEvent event) {
CropImage cropImage = (CropImage) mContext;
if (cropImage.mSaving) {
    return false;
}

switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
    if (cropImage.mWaitingToPick) {
    recomputeFocus(event);
    } else {
    for (int i = 0; i < mHighlightViews.size(); i++) {
        HighlightView hv = mHighlightViews.get(i);
        int edge = hv.getHit(event.getX(), event.getY());
        if (edge != HighlightView.GROW_NONE) {
        mMotionEdge = edge;
        mMotionHighlightView = hv;
        mLastX = event.getX();
        mLastY = event.getY();
        mMotionHighlightView.setMode(
            (edge == HighlightView.MOVE)
            ? HighlightView.ModifyMode.Move
                : HighlightView.ModifyMode.Grow);
        break;
        }
    }
    }
    break;
case MotionEvent.ACTION_UP:
    if (cropImage.mWaitingToPick) {
    for (int i = 0; i < mHighlightViews.size(); i++) {
        HighlightView hv = mHighlightViews.get(i);
        if (hv.hasFocus()) {
        cropImage.mCrop = hv;
        for (int j = 0; j < mHighlightViews.size(); j++) {
            if (j == i) {
            continue;
            }
            mHighlightViews.get(j).setHidden(true);
        }
        centerBasedOnHighlightView(hv);
        ((CropImage) mContext).mWaitingToPick = false;
        return true;
        }
    }
    } else if (mMotionHighlightView != null) {
    centerBasedOnHighlightView(mMotionHighlightView);
    mMotionHighlightView.setMode(
        HighlightView.ModifyMode.None);
    }
    mMotionHighlightView = null;
    break;
case MotionEvent.ACTION_MOVE:
    if (cropImage.mWaitingToPick) {
    recomputeFocus(event);
    } else if (mMotionHighlightView != null) {
    mMotionHighlightView.handleMotion(mMotionEdge,
        event.getX() - mLastX,
        event.getY() - mLastY);
    mLastX = event.getX();
    mLastY = event.getY();

    if (true) {
        // This section of code is optional. It has some user
        // benefit in that moving the crop rectangle against
        // the edge of the screen causes scrolling but it means
        // that the crop rectangle is no longer fixed under
        // the user's finger.
        ensureVisible(mMotionHighlightView);
    }
    }
    break;
}

switch (event.getAction()) {
case MotionEvent.ACTION_UP:
    center(true, true);
    break;
case MotionEvent.ACTION_MOVE:
    // if we're not zoomed then there's no point in even allowing
    // the user to move the image around.  This call to center puts
    // it back to the normalized location (with false meaning don't
    // animate).
    if (getScale() == 1F) {
    center(true, true);
    }
    break;
}

return true;
}

// Pan the displayed image to make sure the cropping rectangle is visible.
private void ensureVisible(HighlightView hv) {
RectF r = hv.mDrawRect;

int panDeltaX1 = (int) Math.max(0, mLeft - r.left);
int panDeltaX2 = (int) Math.min(0, mRight - r.right);

int panDeltaY1 = (int) Math.max(0, mTop - r.top);
int panDeltaY2 = (int) Math.min(0, mBottom - r.bottom);

int panDeltaX = panDeltaX1 != 0 ? panDeltaX1 : panDeltaX2;
int panDeltaY = panDeltaY1 != 0 ? panDeltaY1 : panDeltaY2;

if (panDeltaX != 0 || panDeltaY != 0) {
    panBy(panDeltaX, panDeltaY);
}
}

// If the cropping rectangle's size changed significantly, change the
// view's center and scale according to the cropping rectangle.
private void centerBasedOnHighlightView(HighlightView hv) {
RectF drawRect = hv.mDrawRect;

float width = drawRect.width();
float height = drawRect.height();

float thisWidth = getWidth();
float thisHeight = getHeight();

float z1 = thisWidth / width * .6F;
float z2 = thisHeight / height * .6F;

float zoom = Math.min(z1, z2);
zoom = zoom * this.getScale();
zoom = Math.max(1F, zoom);
if ((Math.abs(zoom - getScale()) / zoom) > .1) {
    float [] coordinates = new float[] {hv.mCropRect.centerX(),
        hv.mCropRect.centerY()};
    getImageMatrix().mapPoints(coordinates);
    zoomTo(zoom, coordinates[0], coordinates[1], 300F);
}

ensureVisible(hv);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < mHighlightViews.size(); i++) {
    mHighlightViews.get(i).draw(canvas);
}
}

public void add(HighlightView hv) {
mHighlightViews.add(hv);
invalidate();
}

提前致谢

最佳答案

我希望这段代码能帮到你..

Uri ImageCaptureUri = Uri.fromFile(new File("filepath"); 
Intent intent = new Intent("com.android.camera.action.CROP"); 
intent.setType("image/*"); 
intent.setData(ImageCaptureUri); 
intent.putExtra("outputX", 200); 
intent.putExtra("outputY", 200); 
intent.putExtra("aspectX", 1); 
intent.putExtra("aspectY", 1); 
intent.putExtra("scale", true); 
intent.putExtra("return-data", true); 
intent.setComponent( new ComponentName(com.android.gallery , com.android.camera.CropImage)); 
startActivityForResult(intent, 1);

关于android - 如何在android中裁剪图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6464123/

有关android - 如何在android中裁剪图像的更多相关文章

  1. ruby - 如何在 Ruby 中顺序创建 PI - 2

    出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits

  2. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  3. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  4. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  5. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  6. ruby - 如何在 Ruby 中拆分参数字符串 Bash 样式? - 2

    我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"

  7. ruby - 如何在 Lion 上安装 Xcode 4.6,需要用 RVM 升级 ruby - 2

    我实际上是在尝试使用RVM在我的OSX10.7.5上更新ruby,并在输入以下命令后:rvminstallruby我得到了以下回复:Searchingforbinaryrubies,thismighttakesometime.Checkingrequirementsforosx.Installingrequirementsforosx.Updatingsystem.......Errorrunning'requirements_osx_brew_update_systemruby-2.0.0-p247',pleaseread/Users/username/.rvm/log/138121

  8. ruby-on-rails - 如何在 ruby​​ 交互式 shell 中有多行? - 2

    这可能是个愚蠢的问题。但是,我是一个新手......你怎么能在交互式ruby​​shell中有多行代码?好像你只能有一条长线。按回车键运行代码。无论如何我可以在不运行代码的情况下跳到下一行吗?再次抱歉,如果这是一个愚蠢的问题。谢谢。 最佳答案 这是一个例子:2.1.2:053>a=1=>12.1.2:054>b=2=>22.1.2:055>a+b=>32.1.2:056>ifa>b#Thecode‘if..."startsthedefinitionoftheconditionalstatement.2.1.2:057?>puts"f

  9. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  10. ruby - 如何在 Rails 4 中使用表单对象之前的验证回调? - 2

    我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser

随机推荐