如何在黑莓中裁剪具有特定形状的图像?

Posted

技术标签:

【中文标题】如何在黑莓中裁剪具有特定形状的图像?【英文标题】:how to crop image with particular shape in Blackberry? 【发布时间】:2012-01-06 13:09:23 【问题描述】:

大家好,感谢阅读我的回答希望你能帮助我

我正在研究黑莓中的图像裁剪。在我的应用程序中包含 3 个主要内容。

1)在屏幕上加载图像

2)选择裁剪区域的形状

3) 在下一个屏幕上显示该裁剪图像而不会丢失其形状

Step1:我可以完成图像加载部分

第 2 步:使用菜单我只需添加 4 种形状

       1)Circle

        2)Rectangle with rounded shape

       3)Star 

       4)Cloud 

当他点击任何菜单项时使用菜单,然后该特定形状的图像将显示在屏幕上。

我们可以赋予该图像移动,因为我们必须让他选择图像的任何部分。

第三步:固定位置后,我们将允许用户使用菜单进行裁剪。 当他单击菜单项“ CROP”时。然后我们必须根据形状裁剪图像,该图像应该显示在下一个屏幕上

注意:以下代码仅适用于矩形,但我想 使用所有形状

这是我的示例代码::

import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.Display;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.MenuItem;
import net.rim.device.api.ui.Screen;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.XYEdges;
import net.rim.device.api.ui.XYRect;
import net.rim.device.api.ui.component.BitmapField;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.component.Menu;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.container.VerticalFieldManager;
import net.rim.device.api.ui.decor.BackgroundFactory;

public class ClipMove extends MainScreen
    Bitmap circle_frame,rectangle_frame,star_frame,cloud_frame,image,selected_frame;
    BitmapField frmae_field;
    private int padding_x=0,padding_y=0;
    private VerticalFieldManager vrt_mgr;
    public ClipMove() 
        //Here my shape images are transparent  
        circle_frame=Bitmap.getBitmapResource("circle.gif");
        rectangle_frame=Bitmap.getBitmapResource("rect1.png");
        star_frame=Bitmap.getBitmapResource("star.gif");
        cloud_frame=Bitmap.getBitmapResource("cloud.gif");

        //this is my actual image to crop
        image=Bitmap.getBitmapResource("sample.jpg"); 

        vrt_mgr=new VerticalFieldManager()
            protected void sublayout(int maxWidth, int maxHeight) 
                super.sublayout(Display.getWidth(),Display.getHeight());
                setExtent(Display.getWidth(),Display.getHeight());
            

        ;
        vrt_mgr.setBackground(BackgroundFactory.createBitmapBackground(image));


        add(vrt_mgr);
    

    protected void makeMenu(Menu menu, int instance) 
        super.makeMenu(menu, instance);
        menu.add(new MenuItem("Rect",0,0) 
            public void run() 
                // TODO Auto-generated method stub
                vrt_mgr.deleteAll();
                selected_frame=rectangle_frame;
                frmae_field=new BitmapField(rectangle_frame);
                vrt_mgr.add(frmae_field);
                vrt_mgr.invalidate();

            
        );

        menu.add(new MenuItem("Circle",0,0) 
            public void run() 
                // TODO Auto-generated method stub
                vrt_mgr.deleteAll();
                selected_frame=circle_frame;
                frmae_field=new BitmapField(circle_frame);
                vrt_mgr.add(frmae_field);
                vrt_mgr.invalidate();

            
        );

        menu.add(new MenuItem("Star",0,0) 
            public void run() 
                // TODO Auto-generated method stub
                vrt_mgr.deleteAll();
                selected_frame=star_frame;
                frmae_field=new BitmapField(star_frame);
                vrt_mgr.add(frmae_field);
                vrt_mgr.invalidate();
            
        );

        menu.add(new MenuItem("Cloud",0,0) 
            public void run() 
                // TODO Auto-generated method stub
                vrt_mgr.deleteAll();
                selected_frame=cloud_frame;
                frmae_field=new BitmapField(cloud_frame);
                vrt_mgr.add(frmae_field);
                vrt_mgr.invalidate();
            
        );
        menu.add(new MenuItem("Crop",0,0) 
            public void run() 
                // TODO Auto-generated method stub
                Field f=vrt_mgr.getField(0);
//              XYRect rect=getFieldExtent(f);
                XYRect rect=new XYRect(padding_x, padding_y,frmae_field.getBitmapWidth(),frmae_field.getBitmapHeight());
                 Bitmap crop = cropImage(image, rect.x, rect.y,
                            rect.width, rect.height);
                 synchronized (UiApplication.getEventLock()) 
                    UiApplication.getUiApplication().pushScreen(new sampleScreen(crop,selected_frame));
                

            
        );

    
    protected boolean navigationMovement(int dx, int dy, int status, int time) 
        if(frmae_field!=null)
            padding_x=padding_x+dx;
            padding_y=padding_y+dy;
            XYEdges edge=new XYEdges(padding_y, 0, 0, padding_x);
            frmae_field.setPadding(edge);
            vrt_mgr.invalidate();
            return true;
        else 
            return false;
        

    

     public void DisplayMessage(final String str)
     
         UiApplication.getUiApplication().invokeLater(new Runnable() 
            public void run() 
                Dialog.inform(str);
            
        );
     
     public XYRect getFieldExtent(Field fld) 
            int cy = fld.getContentTop();
            int cx = fld.getContentLeft();
            Manager m = fld.getManager();
            while (m != null) 
                cy += m.getContentTop() - m.getVerticalScroll();
                cx += m.getContentLeft() - m.getHorizontalScroll();
                if (m instanceof Screen)
                    break;
                m = m.getManager();
            
            return new XYRect(cx, cy, fld.getContentWidth(), fld.getContentHeight());
       
     // this logic only useful for rectangler shape 
     public  Bitmap cropImage(Bitmap image, int x, int y, int width,int height) 
            Bitmap result = new Bitmap(width, height);
            Graphics g = Graphics.create(result);
            g.drawBitmap(0, 0, width, height, image, x, y);
            return result;
     

//this is my next screen to show the croped image 
class sampleScreen extends MainScreen

    VerticalFieldManager manager;
    public sampleScreen(final Bitmap img,final Bitmap back) 
        manager=new VerticalFieldManager()
            protected void paint(Graphics graphics) 
                graphics.drawBitmap(0, 0, img.getWidth(), img.getHeight(), img, 0, 0);
                super.paint(graphics);
            
            protected void sublayout(int maxWidth, int maxHeight) 
                super.sublayout( img.getWidth(), img.getHeight());
                setExtent( img.getWidth(), img.getHeight());
            
        ;
        BitmapField field=new BitmapField(back);
        field.setPadding(0, 0, 0, 0);
        manager.add(field);
        add(manager);
    

我的屏幕截图:

【问题讨论】:

【参考方案1】:

通过使用另一个虚拟图像,可以确定需要删除原始图像的哪些像素(我们可以使它们透明)。虽然它可能不是最优解,但它可以应用于我们可以在 BlackBerry 上绘制的任何几何图形。

检查以下步骤:

创建一个新的位图图像 (dummyImage),其尺寸与 源图片 (myImage)。 使用定义的颜色在其上绘制(填充)目标几何形状 (fillColor)。 现在对于myImage 的每个像素,如果dummyImage 的相同像素 包含fillColor 然后保持不变,否则制作这个像素 通过为其分配零 (0) 使其完全透明。 现在myImage 几乎准备好了,需要修剪此图像 去除透明像素。

以下代码将对图像应用圆形裁剪。 (但不会修剪透明像素)。

package mypackage;

import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.Display;
import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.MenuItem;
import net.rim.device.api.ui.component.BitmapField;
import net.rim.device.api.ui.component.Menu;
import net.rim.device.api.ui.container.MainScreen;

class MyScreen extends MainScreen 
    private Bitmap myImage = Bitmap.getBitmapResource("img/myImage.jpeg");
    private BitmapField _bf;

    public MyScreen() 
        _bf = new BitmapField(myImage);
        adjustBitmapMargin();
        add(_bf);
    

    private void adjustBitmapMargin() 
        int x = (Display.getWidth() - myImage.getWidth()) / 2;
        int y = (Display.getHeight() - myImage.getHeight()) / 2;
        _bf.setMargin(y, 0, 0, x);
    

    protected void makeMenu(Menu menu, int instance) 
        menu.add(miCropCircle);
        super.makeMenu(menu, instance);
    

    private MenuItem miCropCircle = new MenuItem("Crop - Circle", 0, 0) 
        public void run() 
            cropImage();
        
    ;

    private void cropImage() 
        int width = myImage.getWidth();
        int height = myImage.getHeight();

        // get original data from the image
        int myImageData[] = new int[width * height];
        myImage.getARGB(myImageData, 0, width, 0, 0, width, height);

        // get default color of a newly created bitmap
        int defaultColors[] = new int[1 * 1];
        (new Bitmap(1, 1)).getARGB(defaultColors, 0, 1, 0, 0, 1, 1);

        int defaultColor = defaultColors[0];
        int fillColor = Color.RED;
        int diameter = 200;

        // dummy data preparation
        Bitmap dummyImage = new Bitmap(width, height);
        Graphics dummyImageGraphics = Graphics.create(dummyImage);
        dummyImageGraphics.setColor(fillColor);
        int startX = width / 2 - diameter / 2;
        int startY = height / 2 - diameter / 2;
        dummyImageGraphics.fillArc(startX, startY, diameter, diameter, 0, 360);
        int dummyData[] = new int[width * height];
        dummyImage.getARGB(dummyData, 0, width, 0, 0, width, height);

        // filling original data with transparent value.
        int totalPixels = width * height;
        for (int i = 0; i < totalPixels; i++) 
            if (dummyData[i] == defaultColor) 
                myImageData[i] = 0;
            
        

        // set new data
        myImage.setARGB(myImageData, 0, width, 0, 0, width, height);

        // redraw screen
        _bf.setBitmap(myImage);
        adjustBitmapMargin();
        invalidate();

        // free up some memory here
        defaultColors = null;
        dummyImage = null;
        dummyData = null;
        dummyImageGraphics = null;
    

上述代码的输出:

【讨论】:

非常感谢,这里适用于圆形,但我需要知道如何实现其他形状,请指导我\ 检查代码的// dummy data preparation 部分,我用dummyImageGraphics.fillArc(..) 画了一个圆圈。只是你需要在那里画出你想要的几何形状。例如,您可以使用Graphics.drawFillPath(...) 绘制星星。您还可以在那里绘制任何图像(星/云)。

以上是关于如何在黑莓中裁剪具有特定形状的图像?的主要内容,如果未能解决你的问题,请参考以下文章

如何在黑莓中使用经度和纬度获取当前地址

如何防止应用程序在黑莓中启动

如何在黑莓中播放音频作为背景

在黑莓中无延迟播放音频

停止线程并再次开始在黑莓中给出 IllegalThreadStateException

是否可以使用 MapField 在黑莓中移动地图。