2012-01-05 5 views
10

के लिए तेज़ विकल्प मेरे पास BufferedImages को परिवर्तित करने का एक तरीका है जिसका प्रकार TYPE_CUSTOM TYPE_INT_RGB है। मैं निम्नलिखित कोड का उपयोग कर रहा हूं, हालांकि मैं वास्तव में ऐसा करने का एक तेज़ तरीका ढूंढना चाहता हूं।ColorConvertOp

BufferedImage newImg = new BufferedImage(
    src.getWidth(), 
    src.getHeight(), 
    BufferedImage.TYPE_INT_RGB); 

ColorConvertOp op = new ColorConvertOp(null); 
op.filter(src, newImg); 

यह ठीक काम करता है, हालांकि यह काफी धीमा है और मैं सोच रहा हूं कि इस रूपांतरण को करने का एक तेज़ तरीका है या नहीं। रूपांतरण से पहले

ColorModel:

ColorModel: #pixelBits = 24 numComponents = 3 color space = [email protected] transparency = 1 has alpha = false isAlphaPre = false 

ColorModel रूपांतरण के बाद:

DirectColorModel: rmask=ff0000 gmask=ff00 bmask=ff amask=0 

धन्यवाद!


अद्यतन:

कच्चे पिक्सेल डेटा के साथ काम कर बाहर कर देता है सबसे अच्छा तरीका था। चूंकि TYPE_CUSTOM वास्तव में आरजीबी को परिवर्तित कर रहा था, यह मैन्युअल रूप से सरल है और ColorConvertOp से लगभग 95% तेज है।

public static BufferedImage makeCompatible(BufferedImage img) throws IOException { 
    // Allocate the new image 
    BufferedImage dstImage = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB); 

    // Check if the ColorSpace is RGB and the TransferType is BYTE. 
    // Otherwise this fast method does not work as expected 
    ColorModel cm = img.getColorModel(); 
    if (cm.getColorSpace().getType() == ColorSpace.TYPE_RGB && img.getRaster().getTransferType() == DataBuffer.TYPE_BYTE) { 
     //Allocate arrays 
     int len = img.getWidth()*img.getHeight(); 
     byte[] src = new byte[len*3]; 
     int[] dst = new int[len]; 

     // Read the src image data into the array 
     img.getRaster().getDataElements(0, 0, img.getWidth(), img.getHeight(), src); 

     // Convert to INT_RGB 
     int j = 0; 
     for (int i=0; i<len; i++) { 
      dst[i] = (((int)src[j++] & 0xFF) << 16) | 
        (((int)src[j++] & 0xFF) << 8) | 
        (((int)src[j++] & 0xFF)); 
     } 

     // Set the dst image data 
     dstImage.getRaster().setDataElements(0, 0, img.getWidth(), img.getHeight(), dst); 

     return dstImage; 
    } 

    ColorConvertOp op = new ColorConvertOp(null); 
    op.filter(img, dstImage); 

    return dstImage; 
} 

उत्तर

6

BufferedImages दर्दनाक धीमे हैं। मुझे समाधान मिला लेकिन मुझे यकीन नहीं है कि आपको यह पसंद आएगा। Buffered छवियों को संसाधित और परिवर्तित करने का सबसे तेज़ तरीका BufferedImage के अंदर से कच्चे डेटा सरणी निकालना है। आप buffImg.getRaster() को कॉल करके और इसे विशिष्ट रास्टर में परिवर्तित करके करते हैं। फिर raster.getDataStorage() पर कॉल करें। एक बार जब आपके पास कच्चे डेटा तक पहुंच हो तो BufferedImages में सभी अबास्ट्रक्शन के बिना तेज़ छवि प्रसंस्करण कोड लिखना संभव हो जाता है। इस तकनीक को छवि प्रारूपों और आपके हिस्से पर कुछ रिवर्स इंजीनियरिंग की गहराई से समझने की भी आवश्यकता है। यह एकमात्र तरीका है कि मैं अपने अनुप्रयोगों के लिए पर्याप्त तेज़ी से चलाने के लिए छवि प्रसंस्करण कोड प्राप्त करने में सक्षम हूं।

उदाहरण:

ByteInterleavedRaster srcRaster = (ByteInterleavedRaster)src.getRaster(); 
byte srcData[] = srcRaster.getDataStorage(); 

IntegerInterleavedRaster dstRaster = (IntegerInterleavedRaster)dst.getRaster(); 
int dstData[] = dstRaster.getDataStorage(); 

dstData[0] = srcData[0] << 16 | srcData[1] << 8 | srcData[2]; 

या ऐसा ही कुछ। संकलक त्रुटियों की अपेक्षा करें कि आपको निम्न स्तर के रास्टर्स तक पहुंच न पहुंचें। इस तकनीक के साथ मुझे एकमात्र जगह थी एप्पल के अंदर जहां एक प्रवेश उल्लंघन होगा।

+0

सुंदर! कच्चे डेटा के साथ काम करना प्रसंस्करण समय में 95% कटौती !! इस पोस्ट को समाप्त करने के तरीके के लिए संपादित पोस्ट देखें। –

+0

मैंने बाइटइंटरलेवडररस्टर और इंटीजरइंटरलेवडर रास्टर कक्षाओं का उपयोग नहीं किया क्योंकि किसी कारण से मेरे पास सूर्य पैकेज नहीं हैं। –

+0

पवित्र बकवास मैं बस 100 मिनट + psd फ़ाइल को 10 मिनट से 8 सेकंड तक संसाधित करने से चला गया। धन्यवाद! – EdgeCaseBerg

0

आप किसी भी RenderingHints की आपूर्ति करने की कोशिश की है? कोई गारंटी है, लेकिन

ColorConvertOp op = new ColorConvertOp(new RenderingHints(
    RenderingHints.KEY_COLOR_RENDERING, 
    RenderingHints.VALUE_COLOR_RENDER_SPEED)); 

का उपयोग कर के बजाय अपने कोड स्निपेट में null कुछ हद तक वह तेज़ हो सकता है।

+0

की कोशिश की है कि, कोई भाग्य :( –

0

मुझे संदेह है कि समस्या हो सकती है कि ColorConvertOp() पिक्सेल-बाय-पिक्सेल ("धीमी" होने की गारंटी है) काम करता है।

प्रश्न: क्या आपके लिए gc.createCompatibleImage() का उपयोग करना संभव है?

प्रश्न: क्या आपका मूल बिटमैप सही रंग है, या क्या यह एक रंगरूप का उपयोग करता है?

प्रश्न: अन्य सभी को विफल करना, क्या आप जेएनआई इंटरफ़ेस लिखने के लिए सहमत होंगे? या तो अपने, कस्टम सी कोड, या बाहरी पुस्तकालय जैसे ImageMagick पर?

+0

इसके अलावा के लिए < 1ms पंजीकृत करता है - है आपने जावा 6 ++ में किसी भी नए इमेजियो कॉल को देखा है? http://docs.oracle.com/javase/6/docs/api/javax/imageio/ImageIO.html – paulsm4

+0

gc.createCompatibleImage() काम नहीं करेगा (हेडलेस मशीन), बिटमैप सही रंग है, मैं जेएनआई या इमा का उपयोग करने का विरोध नहीं कर रहा हूं geMagick लंबित मैं ColorConvertOp का उपयोग करने के समान परिणाम प्राप्त कर सकता हूं। –

+0

मैं जेपीजी खोलने के लिए मूल त्वरण के साथ छविIO का उपयोग कर रहा हूं। –

0

यदि आपके पास जेएआई स्थापित है तो आप इसे अनइंस्टॉल करने का प्रयास कर सकते हैं, यदि आप कर सकते हैं, या अन्यथा जेपीईजी लोड करते समय कोडेकलिब को अक्षम करने के किसी तरीके को ढूंढ सकते हैं। पिछले जीवन में मेरे पास समान समस्याएं थीं (http://www.java.net/node/660804) और ColorConvertOp उस समय सबसे तेज़ था।

जैसा कि मुझे मौलिक समस्या याद है कि जावा 2 डी सामान्य रूप से TYPE_CUSTOM छवियों के लिए अनुकूलित नहीं है। जब आप जेएआई स्थापित करते हैं तो यह codecLib के साथ आता है जिसमें एक डिकोडर होता है जो TYPE_CUSTOM देता है और डिफ़ॉल्ट के बजाय उपयोग किया जाता है। जेएआई सूची अधिक सहायता प्रदान करने में सक्षम हो सकती है, यह कई सालों से है।

-1

शायद इस प्रयास करें:

Bitmap source = Bitmap.create(width, height, RGB_565);//don't remember exactly... 
Canvas c = new Canvas(source); 
// then 
c.draw(bitmap, 0, 0); 

तब स्रोत बिटमैप संशोधित किया जाएगा।

बाद में आप कर सकते हैं:

onDraw(Canvas canvas){ 
canvas.draw(source, rectSrs,rectDestination, op); 
} 

आप हमेशा प्रबंधन कर सकते हैं, तो बिटमैप का पुन: उपयोग, ताकि आप बेहतर प्रदर्शन प्राप्त करने में सक्षम हो।साथ ही आप अपने बिटमैप को आकर्षित करने के लिए अन्य कैनवास फ़ंक्शंस का उपयोग कर सकते हैं

2

मुझे ColorConvertOp के बजाय 50 बार तेज़ी से Graphics.drawImage() का उपयोग करके प्रतिपादन मिला है। मैं केवल यह मान सकता हूं कि drawImage() GPU त्वरित है।

इस यानी वास्तव में धीमी है, 50ms की तरह 100x200 के लिए एक जाना rectangles

public void BufferdImage convert(BufferedImage input) { 
    BufferedImage output= new BufferedImage(input.getWidht(), input.getHeight(), BufferedImage.TYPE_BYTE_BINARY, CUSTOM_PALETTE); 

    ColorConvertOp op = new ColorConvertOp(input.getColorModel().getColorSpace(), 
              output.getColorModel().getColorSpace()); 

    op.filter(input, output); 
    return output; 
} 

यानी लेकिन यह एक ही आदानों

public void BufferdImage convert(BufferedImage input) { 
    BufferedImage output= new BufferedImage(input.getWidht(), input.getHeight(), BufferedImage.TYPE_BYTE_BINARY, CUSTOM_PALETTE); 

    Graphics graphics = output.getGraphics(); 
    graphics.drawImage(input, 0, 0, null); 
    graphics.dispose(); 
    return output; 
} 
संबंधित मुद्दे