2009-10-26 26 views
14

मेरे पास एक ओपन-सोर्स ऐप है जो फेसबुक पर फोटो अपलोड करता है। बैंडविड्थ को सहेजने के लिए, अपलोड करने से पहले फ़ोटो स्वचालित रूप से आकार बदल जाती हैं (फेसबुक अधिकतम आकार सीमा लगाता है)। कुछ लोगों ने फोटो गुणवत्ता के बारे में शिकायत की है, और वास्तव में आप अंतर देख सकते हैं (कुछ डेमो छवियों के लिए this issue देखें)।छवि का आकार बदलें (जावा)

तो मेरे सवाल है, क्या है गुणवत्ता खोने के बिना जावा में छवियों (अर्थात फोटो) का आकार छोटा करने, या कम से कम, कम से कम गुणवत्ता नुकसान/कलाकृतियों के साथ की "सर्वश्रेष्ठ" तरीका है?

आप वर्तमान कोड देख सकते हैं मेरे पास here है (this page के माध्यम से कोड का आकार बदलें)।

उत्तर

12

मैंने यह सब कोशिश की है - चाल here सहित, और मैं कह सकता हूं कि आप छवि मैगिक का उपयोग करने के लिए बेहतर हैं, जो भी इंटरफ़ेस है, जावा इमेजिंग लाइब्रेरीज़ इस पर आने पर बस स्नफ नहीं कर रहे हैं। इसे सही करने के लिए आपको कई प्रारूपों और एल्गोरिदम का समर्थन करने की आवश्यकता है।

+0

मैं बाहरी कॉल से बचने की उम्मीद कर रहा था लेकिन मुझे लगता है कि आप सही हो सकते हैं। ऐसा लगता है कि जावा अभी तक पूरी तरह से छवि प्रसंस्करण नहीं मिला है! –

+1

यह मेरा निष्कर्ष भी है! जावा छवि apis बस चूसना! मैं आलसीपन के आसपास काम कर सकता हूं, लेकिन खराब छवि गुणवत्ता सिर्फ स्वीकार्य नहीं है! मुझे उम्मीद है कि प्रासंगिक एपीआई को जावाएफएक्स 2.0 के साथ कुछ आवश्यक टीएलसी मिल जाएगा। – Kimble

+1

आप स्पष्ट रूप से [जावा-छवि-स्केलिंग] (http://code.google.com/p/java-image-scaling/) में नहीं आए हैं। –

2

आप किस प्रस्तुति संकेत का उपयोग कर रहे हैं? आमतौर पर बाइबिक resampling सबसे अच्छा होगा। जिन तस्वीरों से आप लिंक कर रहे हैं वे बहुत ही कमजोर हैं, जो मुझे लगता है कि आप अपने संकेत के रूप में निकटतम पड़ोसी का उपयोग कर रहे हैं।

कक्षा में जो आप लिंक करते हैं, paintComponent विधि में, यह छवि का आकार बदलने के छह अलग-अलग साधनों का उपयोग करता है। क्या आपने यह देखने के लिए सभी छः कोशिश की है कि कौन सा सर्वश्रेष्ठ परिणाम देता है?

+0

मैं जोड़ता हूं कि कोड में ऐसा लगता है कि प्रश्नकर्ता के पास "उच्च-गुणवत्ता" मोड है जिसमें कई पास में छवि का आकार बदलना शामिल है। यह एक ही कारण के लिए एक बुरा विचार की तरह लगता है कि आप एक ध्वनि नमूना को बार-बार संपीड़ित और असम्पीडित नहीं करना चाहते हैं; छवि की गुणवत्ता वास्तव में बदतर और बेहतर नहीं होगी। – jprete

+0

हाय, असल में मैंने उन छःों की कोशिश नहीं की है जो मुझे शायद चाहिए। हालांकि मैं बाइबिक रीसाम्प्लिंग का उपयोग कर रहा हूं, जैसा कि आप कहते हैं, "सर्वोत्तम" होना चाहिए। मैं "उच्च गुणवत्ता" मोड का भी उपयोग नहीं कर रहा हूं क्योंकि यह उस स्थिति में काम नहीं करता है, जावा इमेजिंग एपीआई डेडलॉक्स के लिए प्रवण प्रतीत होता है! शायद मेरे कोड के साथ कुछ गलत है, यकीन नहीं है कि क्या। –

0

कुछ निराशाजनक प्रयोगों के बाद मुझे निम्नलिखित resize evaluation मिला, और मेरी परियोजना में बहु-पास दृष्टिकोण को नियोजित किया।

मैं अपने थंबनेल जनरेटर वर्ग में नकल कि getScaledInstance() विधि, बदल मेरी छवि ImageIO (है कि एक एक BufferedImage रिटर्न) का उपयोग करने के दृष्टिकोण पढ़ सकते हैं और अब कर रहा हूँ बहुत खुश ऐसा करने के लिए!

मैंने फ़ोटोशॉप सीएस 3 में किए गए आकार के साथ परिणाम की तुलना की और परिणाम बहुत समान है।

16

फिल, मैं नहीं पता है जो समाधान आपको धीरे-धीरे साथ चला गया है, लेकिन जावा में स्केलिंग छवियों बहुत अच्छी लग रही हो सकता है अगर आप: कि अच्छी तरह से JDK द्वारा समर्थित नहीं हैं

  • बचें BufferedImage प्रकार के। जब वृद्धिशील का उपयोग कर स्केलिंग

मैं इन तरीकों और अच्छी तरह से समर्थित छवि प्रकार के लिए चिपके के साथ वृद्धिशील स्केलिंग के साथ साथ परीक्षण का एक उचित हिस्सा किया है कुंजी है

  • उपयोग स्केलिंग
  • स्टिक वृद्धिशील Bicubic के लिए - - मैंने देखा अलेक्जेंडर का उल्लेख है कि उसे अभी भी इसके साथ अच्छी किस्मत नहीं मिली है जो एक बमर है।

    मैंने 6 महीने पहले imgscalr library (अपाचे 2) जारी किया था, "इस छवि के अच्छे दिखने वाली प्रतियां चाहते हैं," अब यह करें! " SO पर इस तरह के 10 प्रश्नों की तरह कुछ पढ़ने के बाद।

    स्टैंडर्ड उपयोग लगता है: 2 तर्क

    BufferedImage img = ImageIO.read(...); // load image 
    BufferedImage scaledImg = Scalr.resize(img, 640); 
    

    सीमांकन चौड़ाई और ऊंचाई imgscalr छवि को मापना प्रयोग करेंगे - इसके अनुपात सही रखने भले ही आप अमान्य आयामों में पारित कर दिया - वहाँ कई हैं more detailed methods, लेकिन यह सबसे आसान उपयोग है।

    यूज-केस आप चाहते हैं, उदाहरण के लिए यदि 800x600 पिक्सेल के लिए फेसबुक सीमित छवियों, इस प्रकार दिखाई देगा:

    BufferedImage img = ImageIO.read(...); // load image 
    BufferedImage scaledImg = Scalr.resize(img, Method.QUALITY, 800, 600); 
    

    छवि सबसे अच्छा समर्थित चित्र प्रकार में रहता है और साथ बढ़ाया यह सुनिश्चित करेंगे कि जावा उच्चतम गुणवत्ता विधि है कि जावा जरूरी है।

    मेरे अपने उच्च संकल्प परीक्षण में मैं इस लाइब्रेरी का उपयोग कर स्केल की गई छवियों के साथ किसी भी भारी विसंगतियों देखा नहीं है/छोड़कर जब अपनी छवि ImageIO लोडर द्वारा एक खराब समर्थित चित्र प्रकार में डाल दिया जाता है इन तरीकों - उदाहरण के लिए, यदि ऐसा होता जीआईएफ के साथ बहुत कुछ। यदि आप उन्हें इस तरह छोड़ देते हैं और उन्हें उन खराब समर्थित प्रकारों से बाहर नहीं निकालते हैं, तो यह वास्तव में खराब और भयानक लग रहा है।

    इसका कारण यह है कि जावा 2 डी टीम में वास्तव में विभिन्न प्रकार के बुफर्ड इमेज के लिए विभिन्न हार्डवेयर त्वरित पाइपलाइन हैं जो जेडीके संसाधित कर सकते हैं - उन छवि प्रकारों का एक सबसेट जो कम आम हैं, सभी एक ही सॉफ्टवेयर का उपयोग करने के लिए वापस आते हैं Java2D में कवर के तहत पाइपलाइन प्रतिपादन, जिसके परिणामस्वरूप खराब और कभी-कभी पूरी तरह से गलत दिखने वाली छवियां होती हैं। यह व्याख्या करने और कोशिश करने और समझने के लिए ऐसा पीआईए था कि मैंने उस पुस्तकालय को सीधे पुस्तकालय में लिखा था।

    यदि आप उत्सुक हैं तो दो सर्वोत्तम समर्थित प्रकार BufferedImage.TYPE_INT_RGB और _ARGB हैं।

  • +0

    हाय रियाद, के लिए धन्यवाद, इसे बनाने के लिए अपना प्रयास करने के लिए धन्यवाद। यह बहुत अच्छा है और मैंने अभी इसका इस्तेमाल करना शुरू कर दिया है। मुझे गुणवत्ता के साथ समस्या है जब मैं केवल एक विशिष्ट चौड़ाई और ऊंचाई पर एक छवि को पुन: स्थापित करने का प्रयास करता हूं। मेरे पास एक छवि है जो 240X320 है और मुझे इसे 50X75 और 120X180 में आकार बदलना है। मैंने निम्नलिखित कोड का उपयोग करके अलग से दोनों कोशिश की (मैं imgscalr 4.2 का उपयोग कर रहा हूँ)। – WowBow

    +1

    छवि = आकार बदलें (छवि, विधि .ULTRA_QUALITY, 50,75, OP_ANTIALIAS, OP_BRIGHTER); saveImage (छवि, ImageFormatTypes.JPEG, DESTINATION + RESIZED_IMAGE + "।" + ImageFormatTypes.JPEG); मुझे दो समस्याएं हैं। # 1 मैन्युअल रूप से छवि का आकार बदलने के लिए उपयोग किए जाने वाले अन्य आंतरिक उपकरणों की तुलना में बहुत कम गुणवत्ता है। # 2। चौड़ाई 50 से 56 तक और 120 से 135 तक बढ़ जाती है जो अजीब है। क्या आपको कोई विचार है कि ये क्यों हो रहे हैं? तुम्हारी सहायता सराहनीय है। – WowBow

    +2

    @WowBow आह! हां, मुझे लगता है कि मुझे पता है कि क्या हो रहा है ... मुझे नफरत है कि imgscalr अभी तक देव से दूर नहीं है, लेकिन यह कच्चे पिक्सेल मानों पर काम करता है - जब आप इमेजियो के साथ छवि को वापस लिखते हैं, तो यह DEFAULT का उपयोग कर रहा है जेपीजी एन्कोडर सेटिंग्स, जो कि 75% गुणवत्ता पर सेट हैं, मेरा मानना ​​है - आपको "जावा इमेजियो जेपीईजी गुणवत्ता" को Google पर करना है, उदाहरण के लिए कोड को 95% कहने के लिए सेट करें। यदि यह मामला है तो परीक्षण करने के लिए "सस्ता और आसान" तरीका, छवि को पीएनजी (हानि प्रारूप) के रूप में लिखें - यदि यह 'बेहतर तरीका' दिखता है तो यह है। –

    5

    कस्टम गुणवत्ता के उपयोग के साथ छवि का आकार बदलने के लिए thumbnailator.jar।

    उदाहरण कोड http://code.google.com/p/thumbnailator/wiki/Examples

    +1

    संपीड़न स्तर को बदलने के साथ संयोजन में org.imgscalr.Scalr और com.mortennobel.imagescaling दोनों का परीक्षण किया गया है (http://blog.carsoncheng.ca/2011/02/how-to-change-jpeg-compression-in-java.html) और कोई भी काम नहीं किया। थंबनेलेटर कम से कम गुणवत्ता के अनुसार, भयानक था। धन्यवाद! – daker

    0

    मैं उच्चतम गुणवत्ता संरक्षित पहलू अनुपात के साथ आकार परिवर्तन चाहते थे। कुछ चीजों की कोशिश की और कई प्रविष्टियों को पढ़ा। दो दिन खो दिया और अंत में मैं सादे जावा विधि के साथ सबसे अच्छा परिणाम मिला (ImageMagick भी कोशिश की और जावा छवि स्केलिंग पुस्तकालयों):

    public static boolean resizeUsingJavaAlgo(String source, File dest, int width, int height) throws IOException { 
        BufferedImage sourceImage = ImageIO.read(new FileInputStream(source)); 
        double ratio = (double) sourceImage.getWidth()/sourceImage.getHeight(); 
        if (width < 1) { 
        width = (int) (height * ratio + 0.4); 
        } else if (height < 1) { 
        height = (int) (width /ratio + 0.4); 
        } 
    
        Image scaled = sourceImage.getScaledInstance(width, height, Image.SCALE_AREA_AVERAGING); 
        BufferedImage bufferedScaled = new BufferedImage(scaled.getWidth(null), scaled.getHeight(null), BufferedImage.TYPE_INT_RGB); 
        Graphics2D g2d = bufferedScaled.createGraphics(); 
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); 
        g2d.drawImage(scaled, 0, 0, width, height, null); 
        dest.createNewFile(); 
        writeJpeg(bufferedScaled, dest.getCanonicalPath(), 1.0f); 
        return true; 
    } 
    
    
    /** 
    * Write a JPEG file setting the compression quality. 
    * 
    * @param image a BufferedImage to be saved 
    * @param destFile destination file (absolute or relative path) 
    * @param quality a float between 0 and 1, where 1 means uncompressed. 
    * @throws IOException in case of problems writing the file 
    */ 
    private static void writeJpeg(BufferedImage image, String destFile, float quality) 
         throws IOException { 
        ImageWriter writer = null; 
        FileImageOutputStream output = null; 
        try { 
        writer = ImageIO.getImageWritersByFormatName("jpeg").next(); 
        ImageWriteParam param = writer.getDefaultWriteParam(); 
        param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); 
        param.setCompressionQuality(quality); 
        output = new FileImageOutputStream(new File(destFile)); 
        writer.setOutput(output); 
        IIOImage iioImage = new IIOImage(image, null, null); 
        writer.write(null, iioImage, param); 
        } catch (IOException ex) { 
        throw ex; 
        } finally { 
        if (writer != null) { 
         writer.dispose(); 
        } 
        if (output != null) { 
         output.close(); 
        } 
        } 
    } 
    
    5

    दो सबसे लोकप्रिय खुला स्रोत वर्तमान में जावा में आकार बदलने छवि में विशेषज्ञता libs कर रहे हैं:

    Additonal वहाँ जावा केसाथ JDK तरीका है(see this question on how to do it) जो bad results especially with downscaling बनाने के लिए कुख्यात है। Java interface to ImageMagick भी है जिसे यहां छोड़ा जाएगा क्योंकि इसे बाहरी उपकरण की आवश्यकता है।

    दृश्य गुणवत्ता

    यहाँ आकार बदलने/145x213 करने के लिए एक 580x852 png downscaling के परिणामों की तुलना है। संदर्भ के रूप में फ़ोटोशॉप सीएस 5 "वेब के लिए सहेजें" आकार बदलने का उपयोग किया जाता है। नोट: परिणाम 1: 1 हैं जो libs ने सिर्फ एक साथ कॉपी की है। ज़ूम किसी भी फ़िल्टरिंग का उपयोग नहीं करता है, बस एक साधारण निकटतम पड़ोसी एल्गोरिदम।Here you can find the original image.

    comparison

    1. Thumbnailator 0.4।डिफ़ॉल्ट सेटिंग्स, कोई आयाम समायोजन
    2. bicubic एल्गोरिथ्म के साथ
    3. फ़ोटोशॉप CS5
    4. imgscalr 4.2 ULTRA_QUALITY सेटिंग के साथ साथ 8, संकेत VALUE_INTERPOLATION_BICUBIC, VALUE_RENDER_QUALITY प्रस्तुत करना के साथ कोई आयाम समायोजन
    5. Graphics2D (जावा 8), VALUE_ANTIALIAS_ON

    मैं इसे सबसे अच्छा परिणाम चुनने के लिए पाठक को छोड़ देता हूं क्योंकि यह व्यक्तिपरक है। आम तौर पर, Graphics2D को छोड़कर सभी के पास अच्छा आउटपुट होता है। थंबनेलेटर फ़ोटोशॉप आउटपुट के समान ही तेज छवियों को उत्पन्न करता है, जबकि imgscalr का उत्पादन काफी नरम है। आइकन/टेक्स्ट इत्यादि के लिए आप एक तेज आउटपुट चाहते हैं, चित्रों के लिए आप नरम आउटपुट चाहते हैं। 100%, 150%, 200%, 300% और:

    कम्प्यूटेशनल समय

    यहाँ गैर वैज्ञानिक बेंचमार्क ऊपर 2560x1440 करने के लिए 96x96 के बारे में से आयाम के साथ इस tool और 114 छवियों का उपयोग कर 425% छवियों बनाने के रूप में यह इलाज है इसके 400% स्केल संस्करण (इसलिए 114 * 5 स्केलिंग ऑपरेशंस)। सभी libs गुणवत्ता तुलना में समान सेटिंग्स का उपयोग करते हैं (इसलिए उच्चतम गुणवत्ता संभव)। टाइम्स केवल पूरी प्रक्रिया को स्केल नहीं कर रहे हैं। 8 जीबी राम और 5 रन के साथ i5-2520M पर किया गया।

    • Thumbnailator: 7003.0ms | 6581.3ms | 601 9 .1 एमएमएस | 6375.3ms | 8700.3ms
    • imgscalr: 25218.5ms | 25786.6ms | 25095.7ms | 257 9 0.4 एमएमएस | 2 9 2 9 6.3ms
    • ग्राफिक्स 2 डी: 7387.6ms | 7177.0ms | 7048.2ms | 7132.3ms | 7510.3ms

    Here is the code used in this benchmark.

    दिलचस्प बात यह है Thumbnailator भी 6.9 सेकंड औसत समय 7.2 सेकंड एक गरीब 26.2 सेकंड साथ पीछे imgscalr छोड़ने के साथ Java2D द्वारा पीछा के साथ सबसे तेज है। यह शायद उचित नहीं है क्योंकि imgscalr ULTRA_QUALITY पर सेट है जो बेहद महंगा लगता है; QUALITY के साथ यह अधिक प्रतिस्पर्धी 11.1 सेकंड पर औसत रखता है।

    +0

    प्रदर्शन माप कठिन हैं (मैंने इस बारे में कुछ शब्द [इस उत्तर] में लिखा है (http://stackoverflow.com/a/32278737/3182664))। फिर भी, इसके लिए 1 और अन्य उत्तर – Marco13

    +0

    @ मार्को 13 सच है, लेकिन मुझे लगता है कि कम से कम रुझानों को पकड़ने के लिए पर्याप्त नमूना आकार था। – for3st

    +0

    मैंने स्वयं परीक्षणों को पूरा किया और आपके जैसा ही पैटर्न देखा (थंबनेलेटर ने सबसे तेज़ प्रदर्शन प्रदान किया)। मैं अनुशंसा करता हूं कि आप "imgscalr" पंक्ति को दो बार लिख लेंगे (एक बार ULTRA_QUALITY के लिए और एक बार गुणवत्ता के लिए), ताकि बेंचमार्क त्वरित नज़र में अधिक आसानी से तुलनीय हों। –

    संबंधित मुद्दे