छवि आयाम प्राप्त करने का तेज़ तरीका (फ़ाइलें नहीं)


138

मैं पिक्सेल में एक छवि की ऊंचाई और चौड़ाई प्राप्त करने के लिए एक तेज़ तरीके की तलाश कर रहा हूं । इसे कम से कम जेपीजी, पीएनजी और टीआईएफएफ को संभालना चाहिए, लेकिन उतना ही बेहतर। मैं तेजी से जोर देता हूं क्योंकि मेरी छवियां काफी बड़ी हैं (250 एमबी तक) और इमेजमैकिक के साथ आकार प्राप्त करने में बहुत लंबा समय लगता है identifyक्योंकि यह स्पष्ट रूप से छवियों को पहले पूरे के रूप में पढ़ता है।

अधिमानतः, मैं एक रास्ता खोजता हूं जो रूबी में अच्छा काम करता है, या यहां तक ​​कि रेल 3 में भी।

मैं सिद्धांत सामान (विभिन्न छवि प्रारूप, उनके हेडर और उनके अंतर, और इसी तरह) जानता हूं। वास्तव में, मैं कुछ प्रकार के पुस्तकालय के लिए कहता हूं जो मेरे मुद्दे को काफी सामान्य तरीके से हल कर सकते हैं।

मुझे सिर्फ छवियां मिलीं जो आशाजनक लगती हैं हालांकि विकास मृत प्रतीत होता है।


8
यह ImageMagick के नए संस्करणों के लिए सही नहीं लगता है। ImageMagick 6.5.4-7 का उपयोग करते हुए मैंने पुष्टि की है कि पहचान (कम से कम TIF और PNG के लिए) केवल हेडर (60KB तक) पढ़ता है और बहुत तेजी से काम करता है, यहां तक ​​कि 335MB छवियों के लिए भी।
कोडरफॉर्फ़िफ़ेंस

जवाबों:


195
  • fileआदेश कई छवि प्रारूप के लिए आयाम (जैसे PNG, GIF, जेपीईजी, हाल के संस्करण भी पीपीएम, webp) प्रिंट, और केवल शीर्ष लेख पढ़ा है।

  • identifyआदेश (ImageMagick से) छवियों की एक विस्तृत विविधता के लिए छवि में बहुत सारी जानकारी प्रिंट करता है। यह हेडर भाग को पढ़ने के लिए खुद को संयमित करता है (टिप्पणियों को देखें)। इसमें एक एकीकृत आउटपुट भी है जिसका fileदुख की कमी है।

  • exiv2JPEG, TIFF, PNG, GIF, WEBP सहित कई प्रारूपों के लिए आपको आयाम देता है, भले ही कोई EXIF ​​हेडर मौजूद न हो। हालांकि यह स्पष्ट नहीं है कि यह उसके लिए पूरा डेटा पढ़ता है। सभी समर्थित छवि स्वरूपों के लिए exiv2 का मैनपेज देखें।

  • head -n1 आपको पीपीएम, पीजीएम प्रारूपों के लिए आयाम देगा।

वेब पर प्रारूपों लोकप्रिय, दोनों के लिए exiv2और identifyकाम करेगा। उपयोग के मामले के आधार पर आपको अपनी स्क्रिप्ट लिखने की आवश्यकता हो सकती है जो कई उपकरणों के आउटपुट को जोड़ती / पार्स करती है।


3
मैंने इमेजमैगिक आइडेंटिटी कमांड के साथ कुछ टेस्ट किए हैं, स्ट्रेस का उपयोग करके ओपन / रीड / एमएमएपी / क्लोज कॉल रिकॉर्ड करने के लिए कि आइडेंटिफाइड इमेज से कितना डेटा पढ़ा गया है। यह फ़ाइल प्रकार और फ़ाइल आकार पर थोड़ा निर्भर करता है, लेकिन मुझे 5-335 एमबी छवियों के लिए "पहचान" द्वारा 20-60 KB पढ़ा जा रहा था (मैंने "कन्वर्ट" के खिलाफ परीक्षण भी किया था जो सभी बाइट्स पढ़ा जा रहा था)। तो ऐसा लगता है कि यहां "पहचान" एक अच्छा विकल्प है (क्योंकि यह सभी लोकप्रिय प्रारूपों का समर्थन करता है और सिर्फ हेडर पढ़ता है)।
कोडरफॉर्फ़ाइन्ग

1
मुझे लगता है कि exiv2 भी PNG करता है।
चक्स

उस फ़ाइल को पार्स करने का कोई तरीका आउटपुट को आसानी से कमांड करता है? पहचान बहुत अच्छी है, लेकिन यह दुख की बात है कि वेबपी फाइलों के साथ काम नहीं करता है
ब्रायन लीशमैन

पहचानें WebP के साथ काम करती है , और ImageMagick को वर्षों से WebP के लिए समर्थन प्राप्त है। हो सकता है कि आपको अपडेट मिल जाए?
ypnos

32

मुझे यकीन नहीं है कि आपने php इंस्टॉल किया है, लेकिन यह PHP फ़ंक्शन बहुत आसान है

 php -r "print_r(getimagesize('http://www.google.com/images/logos/ps_logo2.png'));"

1
यह "पहचान" की तुलना में बहुत तेज है। अच्छी एप्रोच। धन्यवाद।
स्मार्वब

19

आप ImageMagick की पहचान फ़ंक्शन का उपयोग कर सकते हैं । यहां बताया गया है कि आप इसे कैसे करते हैं (नोट $ 0 छवि का मार्ग है):

width=$(identify -format "%w" "$0")> /dev/null
height=$(identify -format "%h" "$0")> /dev/null

और यह किसी भी संभावित त्रुटि संदेशों को भी छुपाता है। आधुनिक कार्यान्वयन identifyकेवल हेडर को पढ़ते हैं, संपूर्ण छवि को नहीं, इसलिए यह तेज है। हालांकि यह अन्य तरीकों की तुलना कैसे करता है यह सुनिश्चित नहीं है।


2
मेरा मानना ​​है कि यह इस तरह से बहुत अधिक कुशल है:read width height < <(identify -format "%w %h" "${1}")
कॉमरेड

5

https://joseluisbz.wordpress.com/2013/08/06/obtain-size-or-dimension-of-images/ (BMP, PNG, GIF, JPG, TIF या WMF)

यहां दो प्रारूपों पीएनजी और जेपीजी के लिए।

मेरा कोड मेरे उपयोग के लिए डिज़ाइन किए गए वर्ग से है, आप अपनी आवश्यकताओं के अनुसार संपादित कर सकते हैं।

कृपया PHP का उपयोग करके इन कार्यों / विधि की जाँच करें :

  public function ByteStreamImageString($ByteStream,&$Formato,&$Alto,&$Ancho) {
    $Alto = 0;
    $Ancho = 0;
    $Formato = -1;
    $this->HexImageString = "Error";
    if (ord($ByteStream[0])==137 && ord($ByteStream[1])==80 && ord($ByteStream[2])==78){
      $Formato = 1; //PNG
      $Alto = $this->Byte2PosInt($ByteStream[22],$ByteStream[23]);
      $Ancho = $this->Byte2PosInt($ByteStream[18],$ByteStream[19]);
    }
    if (ord($ByteStream[0])==255 && ord($ByteStream[1])==216
        && ord($ByteStream[2])==255 && ord($ByteStream[3])==224){
      $Formato = 2; //JPG
      $PosJPG = 2;
      while ($PosJPG<strlen($ByteStream)){
        if (sprintf("%02X%02X", ord($ByteStream[$PosJPG+0]),ord($ByteStream[$PosJPG+1]))=="FFC0"){
          $Alto = $this->Byte2PosInt($ByteStream[$PosJPG+5],$ByteStream[$PosJPG+6]);
          $Ancho = $this->Byte2PosInt($ByteStream[$PosJPG+7],$ByteStream[$PosJPG+8]);
        }
        $PosJPG = $PosJPG+2+$this->Byte2PosInt($ByteStream[$PosJPG+2],$ByteStream[$PosJPG+3]);
      }
    }
    if ($Formato > 0){
      $this->HexImageString = "";
      $Salto = 0;
      for ($i=0;$i < strlen($ByteStream); $i++){
        $Salto++;
        $this->HexImageString .= sprintf("%02x", ord($ByteStream[$i]));
        if ($Salto==64){
          $this->HexImageString .= "\n";
          $Salto = 0;
        }
      }
    }
  }


  private function Byte2PosInt($Byte08,$Byte00) {
    return ((ord($Byte08) & 0xFF) << 8)|((ord($Byte00) & 0xFF) << 0);
  }

PHP कोड का उपयोग करना:

      $iFormato = NULL;//Format PNG or JPG
      $iAlto = NULL; //High
      $iAncho = NULL;//Wide
      ByteStreamImageString($ImageJPG,$iFormato,$iAlto,$iAncho);//The Dimensions will stored in  iFormato,iAlto,iAncho

अब ये कार्य / विधि जावा का उपयोग कर :

  private void ByteStreamImageString(byte[] ByteStream,int[] Frmt,int[] High,int[] Wide) {
    High[0] = 0;
    Wide[0] = 0;
    Frmt[0] = -1;
    this.HexImageString = "Error";
    if ((int)(ByteStream[0]&0xFF)==137 && (int)(ByteStream[1]&0xFF)==80 &&(int)(ByteStream[2]&0xFF)==78){
      Frmt[0] = 1; //PNG
      High[0] = this.Byte2PosInt(ByteStream[22],ByteStream[23]);
      Wide[0] = this.Byte2PosInt(ByteStream[18],ByteStream[19]);
    }
    if ((int)(ByteStream[0]&0xFF)==255 && (int)(ByteStream[1]&0xFF)==216
        &&(int)(ByteStream[2]&0xFF)==255 && (int)(ByteStream[3]&0xFF)==224){
      Frmt[0] = 2; //JPG
      int PosJPG = 2;
      while (PosJPG<ByteStream.length){
        if (String.format("%02X%02X", ByteStream[PosJPG+0],ByteStream[PosJPG+1]).equals("FFC0")){
          High[0] = this.Byte2PosInt(ByteStream[PosJPG+5],ByteStream[PosJPG+6]);
          Wide[0] = this.Byte2PosInt(ByteStream[PosJPG+7],ByteStream[PosJPG+8]);
        }
        PosJPG = PosJPG+2+this.Byte2PosInt(ByteStream[PosJPG+2],ByteStream[PosJPG+3]);
      }
    }
    if (Frmt[0] > 0){
      this.HexImageString = "";
      int Salto = 0;
      for (int i=0;i < ByteStream.length; i++){
        Salto++;
        this.HexImageString += String.format("%02x", ByteStream[i]);
        if (Salto==64){
          this.HexImageString += "\n";
          Salto = 0;
        }
      }
    }
  }


  private Integer Byte2PosInt(byte Byte08, byte Byte00) {
    return new Integer (((Byte08 & 0xFF) << 8)|((Byte00 & 0xFF) << 0));
  }

जावा कोड का उपयोग करना:

        int[] iFormato = new int[1]; //Format PNG or JPG
        int[] iAlto = new int[1]; //High
        int[] iAncho = new int[1]; //Wide
        ByteStreamImageString(ImageJPG,iFormato,iAlto,iAncho); //The Dimensions will stored in  iFormato[0],iAlto[0],iAncho[0]

मुझे लगता है कि आप जावा में ref/ outपैरामीटर प्राप्त करने के लिए हैक के रूप में तर्क के लिए सरणियों का उपयोग कर रहे हैं - क्या इसे सबसे अच्छा अभ्यास माना जाता है?
दाई

यह उत्तर बहुत पुराना है, अब मैं अपडेट करने के लिए तैयार नहीं हूं (मैं बहुत सारी चीजें भूल गया हूं और मेरे पास समय नहीं है), लेकिन आप कोड की जांच कर सकते हैं और इसे संपादित कर सकते हैं।
joseluisbz

joseluisbz.wordpress.com/2013/07/26/… (WMF के लिए स्पष्टीकरण)
joseluisbz

इस उदाहरण के लिए मैं 3 वर्गों, प्रारूप, उच्च और चौड़ाई के साथ एक नए वर्ग को लागू करने की सलाह देता हूं, इस वर्ग का एक उदाहरण लौटाता हूं।
जोसेलबसबज

1

यह पिक्सेल आयाम आप चाहते हैं (चौड़ाई और ऊंचाई), मुझे लगता है?

मुझे लगता है कि अधिकांश फ़ाइल स्वरूपों में आयामों को परिभाषित करने वाली कुछ हेडर जानकारी होती है, जिससे फ़ाइल को पढ़ने वाले सॉफ़्टवेयर को पता चल सकता है कि फ़ाइल को पढ़ना शुरू करने से पहले उसे कितना कमरा आरक्षित करना चाहिए। कुछ "कच्ची" प्रकार की फ़ाइल स्वरूप बस बाइट्स की एक धारा हो सकती है जिसमें कुछ "लाइन के अंत" बाइट होते हैं, प्रत्येक क्षैतिज पंक्ति में पिक्सेल की पंक्ति (जिस स्थिति में सॉफ़्टवेयर को पहली पंक्ति पढ़नी चाहिए और बाइट स्ट्रीम का आकार विभाजित करना होगा ऊंचाई पाने के लिए लाइन की लंबाई से)।

मुझे नहीं लगता कि आप इसे किसी भी "सामान्य" तरीके से बना सकते हैं, क्योंकि आपको यह पढ़ने के लिए जानने के लिए फ़ाइल प्रारूप (या पाठ्यक्रम की लाइब्रेरी का उपयोग करना) को समझने की आवश्यकता है। आप शायद कुछ कोड पा सकते हैं जो ज्यादातर मामलों में पूरी फ़ाइल को पढ़ने के बिना आयामों का एक मोटा अनुमान देते हैं, लेकिन मुझे लगता है कि कुछ फाइलपेट्स को आपको पूरी फाइल पढ़ने की आवश्यकता हो सकती है ताकि यह सुनिश्चित हो सके कि वास्तव में क्या आयाम हैं। मुझे उम्मीद है कि अधिकांश वेब केंद्रित छवि प्रारूपों में इस तरह की जानकारी के साथ एक हेडर होता है ताकि ब्राउज़र पूरी छवि लोड होने से पहले बॉक्स आयाम बना सके।

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

अपडेट : imageinfo ऐसा लगता है कि यह वही करता है जो आप चाहते हैं। (इसका परीक्षण नहीं किया है)


यह उपकरण उतनी ही तेजी से काम करता है जितना मुझे इसकी आवश्यकता है;)। मैं देखूंगा कि क्या मैं इसका सही इस्तेमाल कर सकता हूं।
dnnjou

0

यदि आपको छवियों में EXIF ​​जानकारी है, तो आप केवल EXIF ​​शीर्ष लेख पढ़ सकते हैं।


दुर्भाग्य से मुझे नहीं पता कि वहाँ किस तरह की छवियां होंगी और क्या उनके पास EXIF ​​डेटा है।
dnnjou

3
आपकी छवियों में से कितने है कि जानकारी नहीं है? हो सकता है कि यदि उनमें से 90% में EXIF ​​डेटा हो तो अन्य 10% पर ImageMagick का उपयोग करने की सुस्ती स्वीकार्य होगी।
एंडी लेस्टर

इस उत्तर में गिरावट क्यों है? यह प्रश्न का एक मान्य उत्तर है और ठीक वही हो सकता है जो ओपी या कोई और देख रहा है।
को शेपर्ड

0

-पिंग एक ऐसा विकल्प है जो लगता है कि उस उद्देश्य के लिए परिचय है।

हालाँकि ImageMagick 6.7.7 के रूप में मैं हर बड़ी फ़ाइलों के लिए भी मंदी का निरीक्षण नहीं करता, जैसे:

head -c 100000000 /dev/urandom > f.gray
# I don't recommend that you run this command as it eats a lot of memory.
convert -depth 8 -size 20000x10000 f.gray f.png
identify f.png

क्या आप एक उदाहरण इनपुट छवि का उत्पादन कर सकते हैं जिसके लिए यह अभी भी धीमा है?


0

tldr: फाइल "इमेजेनम" करेगा

वेब के साथ काम करता है, सभी jpg प्रारूप (jpeg, jpg200, ..),

सैंपल आउटपुट जैसा दिखता है

JPEG छवि डेटा, JFIF मानक 1.02, पहलू अनुपात, घनत्व 1x1, खंड लंबाई 16, आधार रेखा, सटीक 8, 650x400, फ्रेम 3

एक अजगर सूची में फ़ाइल के उत्पादन को लोड करें और सूची में 4'th क्षेत्र का उपयोग करें।

FYI करें, नेटवर्क ट्रैफ़िक में कटौती करने के लिए लगभग 18000+ छवियों का अनुकूलन किया।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.