Ankündigung

Einklappen
Keine Ankündigung bisher.

[Erledigt] imagecreatefrombmp(): 16 Bit Bitmaps mit Palette

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • [Erledigt] imagecreatefrombmp(): 16 Bit Bitmaps mit Palette

    Hier die fertige Funktion:
    function imagecreatefrombmp(): Läuft mit allen Bitraten! - Forum: PHP

    Wie alles begann:
    Hi,

    ich suche wie ein Verrückter nach einer funktionierenden imagecreatefrombmp() Funktion. Nun habe ich aus mehreren Quellen was gebaut, was ziemlich zuverlässig funktioniert:
    PHP-Code:
    function imagecreatefrombmp4($filename) {
        if (!(
    $fh fopen($filename'rb'))) {
            return 
    false;
        }
        
    $file unpack('vfile_type/Vfile_size/Vreserved/Vbitmap_offset'fread($fh14));
        
    // bitmap check
        
    if ($file['file_type'] != 19778) {
            return 
    false;
        }
        
    $bmp unpack('Vheader_size/Vwidth/Vheight/vplanes/vbits_per_pixel/Vcompression/Vsize_bitmap/Vhoriz_resolution/Vvert_resolution/Vcolors_used/Vcolors_important'fread($fh40));
        
    $bmp['colors'] = pow(2$bmp['bits_per_pixel']);
        if (
    $bmp['size_bitmap'] == 0) {
            
    $bmp['size_bitmap'] = $file['file_size'] - $file['bitmap_offset'];
        }
        
    $bmp['bytes_per_pixel'] = $bmp['bits_per_pixel'] / 8;
        
    $bmp['bytes_per_pixel2'] = ceil($bmp['bytes_per_pixel']);
        
    $bmp['decal'] = ($bmp['width'] * $bmp['bytes_per_pixel'] / 4);
        
    $bmp['decal'] -= floor($bmp['width'] * $bmp['bytes_per_pixel'] / 4);
        
    $bmp['decal'] = - ($bmp['decal']);
        if (
    $bmp['decal'] == 4) {
            
    $bmp['decal'] = 0;
        }
        
    $palette = array();
        if (
    $bmp['colors'] < 16777216) {
            if (!(
    $palette = @unpack('V' $bmp['colors'], fread($fh$bmp['colors'] * 4)))) {
                
    // no palette found: rewind
                
    $palette = array();
                
    fseek($fh54);
            }
        }
        
    $img fread($fh$bmp['size_bitmap']);
        
    $vide chr(0);
        
    $res imagecreatetruecolor($bmp['width'], $bmp['height']);
        
    $p 0;
        
    $y $bmp['height'] - 1;
        while (
    $y >= 0) {
            
    $x 0;
            while (
    $x $bmp['width']) {
                switch (
    $bmp['bits_per_pixel']) {
                    case 
    24:
                        
    $color = @unpack('V'substr($img$p3) . $vide);
                        if (!
    $color) {
                            break;
                        }
                        break;
                    case 
    16:
                        
    // some have palette
                        
    if ($palette) {
                            
    $color = @unpack('n'substr($img$p2));
                            if (!
    $color) {
                                break;
                            }
                            
    $color[1] = $palette$color[1] ];
                        }
                        else {
                            
    $color = @unpack('v'substr($img$p2));
                            if (!
    $color) {
                                break;
                            }
                            
    $color[1] = (($color[1] & 0xf800) >> 8) * 65536 + (($color[1] & 0x07e0) >> 3) * 256 + (($color[1] & 0x001f) << 3);
                        }
                        break;
                    case 
    8:
                        
    $color = @unpack('n'$vide substr($img$p1));
                        if (!
    $color) {
                            break;
                        }
                        
    $color[1] = $palette$color[1] + ];
                        break;
                    case 
    4:
                        
    $color = @unpack('n'$vide substr($imgfloor($p), 1));
                        if (!
    $color) {
                            break;
                        }
                        
    $color[1] = ($p 2) % == $color[1] >> $color[1] & 0x0F;
                        
    $color[1] = $palette$color[1] + ];
                        break;
                    case 
    1:
                        
    $color = @unpack('n'$vide substr($imgfloor($p), 1));
                        if (!
    $color) {
                            break;
                        }
                        switch ((
    $p 8) % 8) {
                            case 
    0:
                                
    $color[1] = $color[1] >> 7;
                                break;
                            case 
    1:
                                
    $color[1] = ($color[1] & 0x40) >> 6;
                                break;
                            case 
    2:
                                
    $color[1] = ($color[1] & 0x20) >> 5;
                                break;
                            case 
    3:
                                
    $color[1] = ($color[1] & 0x10) >> 4;
                                break;
                            case 
    4:
                                
    $color[1] = ($color[1] & 0x8) >> 3;
                                break;
                            case 
    5:
                                
    $color[1] = ($color[1] & 0x4) >> 2;
                                break;
                            case 
    6:
                                
    $color[1] = ($color[1] & 0x2) >> 1;
                                break;
                            case 
    7:
                                
    $color[1] = ($color[1] & 0x1);
                                break;
                        }
                        
    $color[1] = $palette$color[1] + ];
                        break;
                    default:
                        return 
    false;
                }
                
    imagesetpixel($res$x$y$color[1]);
                
    $x++;
                
    $p += $bmp['bytes_per_pixel'];
            }
            
    $y--;
            
    $p += $bmp['decal'];
        }
        
    fclose($fh);
        return 
    $res;

    Alle 16 Bit Bilder ohne Palette funktionieren tadellos. Aber bei denen mit Palette sieht es so aus:


    Nun dachte ich, da ja 16 Bit ohne Palette funktioniert, dass ich die einfach mal unset()'e aber das resultiert dann das:


    Also die Farben stimmen, aber das ganze ist nach wie vor verschoben. Wie viel von dem Bild ausgegeben wird, hängt vom Bild ab. Hier sieht man z.b. noch weniger:


    Für 32 Bit habe ich übrigens auch noch keine Lösung, aber 16 Bit ist erstmal wichtiger

    Bei meiner Recherche bin ich übrigens noch über die Variante gestolpert, die aber mit 16 Bit-Bildern überhaupt nicht umgehen kann (egal ob Palette oder nicht). 32 Bit habe ich noch nicht getestet. Sowohl die 16 Bit als auch die 32 Bit Regeln habe ich auf Grund weiterer Netzfunde hinzugefügt:
    PHP-Code:
    function bmp2gd($src$dest false) {
        if(!(
    $src_f fopen($src'rb'))) {
            return 
    false;
        }
        if(!(
    $dest_f fopen($dest'wb'))) {
            return 
    false;
        }
        
    $header unpack('vtype/Vsize/v2reserved/Voffset'fread($src_f14));
        
    $info unpack('Vsize/Vwidth/Vheight/vplanes/vbits/Vcompression/Vimagesize/Vxres/Vyres/Vncolor/Vimportant'fread($src_f40));
        
    extract($info);
        
    extract($header);
        
    // check for bitmap
        
    if ($type != 0x4D42) {
            return 
    false;
        }
        
    $palette_size $offset 54;
        
    $ncolor $palette_size 4;
        
    $gd_header '';
        
    // true-color vs. palette
        
    $gd_header .= ($palette_size == 0) ? "\xFF\xFE" "\xFF\xFF";
        
    $gd_header .= pack('n2'$width$height);
        
    $gd_header .= ($palette_size == 0) ? "\x01" "\x00";
        if(
    $palette_size) {
            
    $gd_header .= pack('n'$ncolor);
        }
        
    // no transparency
        
    $gd_header .= "\xFF\xFF\xFF\xFF";
        
    fwrite($dest_f$gd_header);
        if(
    $palette_size) {
            
    $palette fread($src_f$palette_size);
            
    $gd_palette '';
            
    $j 0;
            while(
    $j $palette_size) {
                
    $b $palette{$j++};
                
    $g $palette{$j++};
                
    $r $palette{$j++};
                
    $a $palette{$j++};
                
    $gd_palette .= $r $g $b $a;
            }
            
    $gd_palette .= str_repeat("\x00\x00\x00\x00"256 $ncolor);
            
    fwrite($dest_f$gd_palette);
        }
        
    $scan_line_size = (($bits $width) + 7) >> 3;
        
    $scan_line_align = ($scan_line_size 0x03) ? - ($scan_line_size 0x03) : 0;
        for(
    $i 0$l $height 1$i $height$i++, $l--) {
            
    // BMP stores scan lines starting from bottom
            
    fseek($src_f$offset + (($scan_line_size $scan_line_align) * $l));
            
    $scan_line fread($src_f$scan_line_size);
            switch (
    $bits) {
                case 
    32:
                    
    $gd_scan_line '';
                    
    $j 0;
                    while(
    $j $scan_line_size) {
                        
    $b $scan_line{$j++};
                        
    $g $scan_line{$j++};
                        
    $r $scan_line{$j++};
                        
    $a chr(255 ord($scan_line{$j++}));
                        
    $gd_scan_line .= $a $r $g $b;
                    }
                    break;
                case 
    24:
                    
    $gd_scan_line '';
                    
    $j 0;
                    while(
    $j $scan_line_size) {
                        
    $b $scan_line{$j++};
                        
    $g $scan_line{$j++};
                        
    $r $scan_line{$j++};
                        
    $gd_scan_line .= "\x00" $r $g $b;
                    }
                    break;
                case 
    16:
                    
    $gd_scan_line '';
                    
    $j 0;
                    while (
    $j $scan_line_size) {
                        
    $byte1 $scan_line{$j++};
                        
    $byte2 $scan_line{$j++};
                        
    $b chr($byte1 >> 3) * (255 31);
                        
    $g = (chr($byte1 0x07) + chr($byte2 >> 5)) * (255 63);
                        
    $r chr($byte2 0x1F) * (255 31);
                        
    $gd_scan_line .= "\x00" $r $g $b;
                    }
                    break;
                case 
    8:
                    
    $gd_scan_line $scan_line;
                    break;
                case 
    4:
                    
    $gd_scan_line '';
                    
    $j 0;
                    while(
    $j $scan_line_size) {
                        
    $byte ord($scan_line{$j++});
                        
    $p1 chr($byte >> 4);
                        
    $p2 chr($byte 0x0F);
                        
    $gd_scan_line .= $p1 $p2;
                    }
                    
    $gd_scan_line substr($gd_scan_line0$width);
                    break;
                case 
    1:
                    
    $gd_scan_line '';
                    
    $j 0;
                    while(
    $j $scan_line_size) {
                        
    $byte ord($scan_line{$j++});
                        
    $p1 chr((int) (($byte 0x80) != 0));
                        
    $p2 chr((int) (($byte 0x40) != 0));
                        
    $p3 chr((int) (($byte 0x20) != 0));
                        
    $p4 chr((int) (($byte 0x10) != 0));
                        
    $p5 chr((int) (($byte 0x08) != 0));
                        
    $p6 chr((int) (($byte 0x04) != 0));
                        
    $p7 chr((int) (($byte 0x02) != 0));
                        
    $p8 chr((int) (($byte 0x01) != 0));
                        
    $gd_scan_line .= $p1 $p2 $p3 $p4 $p5 $p6 $p7 $p8;
                    }
                    
    $gd_scan_line substr($gd_scan_line0$width);
                    break;
            }
            
    fwrite($dest_f$gd_scan_line);
        }
        
    fclose($src_f);
        
    fclose($dest_f);
        return 
    true;
    }
    function 
    imagecreatefrombmp7($filename) {
        
    $tmp_name tempnam('/tmp''GD');
        if (
    bmp2gd($filename$tmp_name)) {
            
    $img imagecreatefromgd($tmp_name);
            
    unlink($tmp_name);
            return 
    $img;
        }
        return 
    false;

    Vielleicht ist ja jemand fit in Bit-Verschiebungen und weiß eine Lösung?!

    Dazu auch mal die Definition zu 16 Bit Bitmaps laut Wikipedia:
    Windows Bitmap – Wikipedia
    meine [url=http://www.programmierer-forum.de/php-forum-f1050.htm]PHP Scripte[/url]


  • #2
    Sorry, aber mit komplett unkommentierten Code und ohne weitere Ausführungen hier anzurücken, finde ich ja etwas dreist.
    --

    „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
    Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


    --

    Kommentar


    • #3
      Nun der Code ist nicht von mir und die Bit-Extraktion verstehe ich zu wenig, um sie kommentieren zu können. Was willst Du denn wissen?

      EDIT:
      Upps, ich sehe gerade, dass ich beim Editieren einen Teil meines Beitrags überschrieben habe. Mist.

      Ich versuche es mal wiederherzustellen. Also im ersten Schritt wird bei jedem Bild geprüft ob in den Meta-Daten eine Palette vorhanden ist:
      PHP-Code:
          $palette = array(); 
          if (
      $bmp['colors'] < 16777216) { 
              if (!(
      $palette = @unpack('V' $bmp['colors'], fread($fh$bmp['colors'] * 4)))) { 
                  
      // no palette found: rewind 
                  
      $palette = array(); 
                  
      fseek($fh54); 
              } 
          } 
      Ein 16 Bit Bild kann im Gegensatz zu den Kommentaren bei php.net sehr wohl auch eine Palette haben.

      Im Falle von 16 Bit greift dann dieser Part:
      PHP-Code:
                      case 16
                          
      // some have palette 
                          
      if ($palette) { 
                              
      $color = @unpack('n'substr($img$p2)); 
                              if (!
      $color) { 
                                  break; 
                              } 
                              
      $color[1] = $palette$color[1] ]; 
                          } 
                          else { 
                              
      $color = @unpack('v'substr($img$p2)); 
                              if (!
      $color) { 
                                  break; 
                              } 
                              
      $color[1] = (($color[1] & 0xf800) >> 8) * 65536 + (($color[1] & 0x07e0) >> 3) * 256 + (($color[1] & 0x001f) << 3); 
                          } 
                          break; 
      Die ohne Palette funktionieren wie gesagt wie gewünscht. Wenn es aber eine Palette gibt, ensteht das oben genannte 1. Bild. Schmeiße ich diese Palette dann manuell raus, so dass der Else-Teil greift, so sehe ich das 2. Bild mit korrekten Farben, aber immer noch verschobenem Inhalt.

      EDIT2:
      Ok so viel habe ich schon mal:
      16 Bit hat doch keine Palette. Es gab nur zufälligerweise Bilder, in denen die ausgelesenen Bytes als Palette erkannt wurden. Allerdings hat 16 Bit einen größeren Header. Den versuche ich jetzt gerade zu extrahieren und herauszufinden, was da drin steht. Später mehr dazu...
      meine [url=http://www.programmierer-forum.de/php-forum-f1050.htm]PHP Scripte[/url]

      Kommentar


      • #4
        PHP-Code:
            if ($bmp['colors'] < 16777216) {
                if (!(
        $palette = @unpack('V' $bmp['colors'], fread($fh$bmp['colors'] * 4)))) { 
        Du gehst bei einer 16Bit Palette davon aus, das jeder Farbwert mit 4 Byte kodiert ist... isses aber nicht (siehe auch wikipedia)
        16 bpp:
        Das Format ist wie bei BI_BITFIELDS, wenn folgende Farbmasken verwendet würden:

        0x00007C00 für den Rot-Kanal
        0x000003E0 für den Grün-Kanal
        0x0000001F für den Blau-Kanal

        Jeder Farbkanal ist 5 Bit pro Pixel groß; insgesamt ergeben sich 32.768 mögliche Farben (ein Bit ist ungenutzt).
        Dadurch liest du bereits Bilddaten in die Palette und bekommst nur ein halbes Bild. Die falschen Farben ergeben sich übrigens auch daraus
        Über 90% aller Gewaltverbrechen passieren innerhalb von 24 Stunden nach dem Konsum von Brot.

        Kommentar


        • #5
          Jo, hatte ich in meinem EDIT schon erkannt.

          Bei 16-Bit griff das Auslesen der Palette eigentlich nur zufällig und ich dachte deswegen, dass es eine geben müsse. Tat es aber nicht. Stattdessen hatte ich eigentlich nur das Problem, dass bei 16-Bit 5:6:5 maskierten Bitmaps ein zusätzlicher Header (rMask, gMask & bMask) ausgelesen werden muss bzw. dieser hätte übersprungen werden müssen, um an das erste Byte des Bilder zu kommen.

          Erst wusste ich nichts mit den Mask-Werten anzufangen, bin dann aber hier und hier schnell fündig geworden.

          Damit steht nun die Version, die auch mit 16-Bit Bitmaps umgehen kann:
          PHP-Code:
          if (!function_exists('imagecreatefrombmp')) { function imagecreatefrombmp($filename) {
              if (!(
          $fh fopen($filename'rb'))) {
                  
          trigger_error('imagecreatefrombmp: Can not open ' $filenameE_USER_WARNING);
                  return 
          false;
              }
              
          // read file header
              
          $meta unpack('vtype/Vfilesize/Vreserved/Voffset'fread($fh14));
              
          // check for bitmap
              
          if ($meta['type'] != 19778) {
                  
          trigger_error('imagecreatefrombmp: ' $filename ' is not a bitmap!'E_USER_WARNING);
                  return 
          false;
              }
              
          // read image header
              
          $meta += unpack('Vheadersize/Vwidth/Vheight/vplanes/vbits/Vcompression/Vimagesize/Vxres/Vyres/Vncolor/Vimportant'fread($fh40));
              
          // read 16-Bit header
              
          if ($meta['bits'] == 16) {
                  
          $meta += unpack('VrMask/VgMask/VbMask'fread($fh12));
              }
              
          // build general meta data
              
          $meta['colors'] = pow(2$meta['bits']);
              if (
          $meta['imagesize'] == 0) {
                  
          $meta['imagesize'] = $meta['filesize'] - $meta['offset'];
              }
              
          $meta['bytes'] = $meta['bits'] / 8;
              
          $meta['decal'] = - (* (($meta['width'] * $meta['bytes'] / 4)- floor($meta['width'] * $meta['bytes'] / 4)));
              if (
          $meta['decal'] == 4) {
                  
          $meta['decal'] = 0;
              }
              
          // read palette
              
          $palette = array();
              if (
          $meta['colors'] < 16777216 && $meta['colors'] != 65536) {
                  
          $palette unpack('V' $meta['colors'], fread($fh$meta['colors'] * 4));
              }
              
          // create gd image
              
          $im imagecreatetruecolor($meta['width'], $meta['height']);
              
          $data fread($fh$meta['imagesize']);
              
          $p 0;
              
          $vide chr(0);
              
          $y $meta['height'] - 1;
              while (
          $y >= 0) {
                  
          $x 0;
                  while (
          $x $meta['width']) {
                      switch (
          $meta['bits']) {
                          case 
          24:
                              
          $color unpack('V'substr($data$p3) . $vide);
                              break;
                          case 
          16:
                              
          $color unpack('v'substr($data$p2));
                              
          $color[1] = (($color[1] & 0xf800) >> 8) * 65536 + (($color[1] & 0x07e0) >> 3) * 256 + (($color[1] & 0x001f) << 3);
                              break;
                          case 
          8:
                              
          $color unpack('n'$vide substr($data$p1));
                              
          $color[1] = $palette$color[1] + ];
                              break;
                          case 
          4:
                              
          $color unpack('n'$vide substr($datafloor($p), 1));
                              if (!
          $color) {
                                  break;
                              }
                              
          $color[1] = ($p 2) % == $color[1] >> $color[1] & 0x0F;
                              
          $color[1] = $palette$color[1] + ];
                              break;
                          case 
          1:
                              
          $color unpack('n'$vide substr($datafloor($p), 1));
                              if (!
          $color) {
                                  break;
                              }
                              switch ((
          $p 8) % 8) {
                                  case 
          0:
                                      
          $color[1] = $color[1] >> 7;
                                      break;
                                  case 
          1:
                                      
          $color[1] = ($color[1] & 0x40) >> 6;
                                      break;
                                  case 
          2:
                                      
          $color[1] = ($color[1] & 0x20) >> 5;
                                      break;
                                  case 
          3:
                                      
          $color[1] = ($color[1] & 0x10) >> 4;
                                      break;
                                  case 
          4:
                                      
          $color[1] = ($color[1] & 0x8) >> 3;
                                      break;
                                  case 
          5:
                                      
          $color[1] = ($color[1] & 0x4) >> 2;
                                      break;
                                  case 
          6:
                                      
          $color[1] = ($color[1] & 0x2) >> 1;
                                      break;
                                  case 
          7:
                                      
          $color[1] = ($color[1] & 0x1);
                                      break;
                              }
                              
          $color[1] = $palette$color[1] + ];
                              break;
                          default:
                              
          trigger_error('imagecreatefrombmp: ' $meta['bits'] . ' bits are not supported!'E_USER_WARNING);
                              return 
          false;
                      }
                      
          imagesetpixel($im$x$y$color[1]);
                      
          $x++;
                      
          $p += $meta['bytes'];
                  }
                  
          $y--;
                  
          $p += $meta['decal'];
              }
              
          fclose($fh);
              return 
          $im;
          }} 
          Jetzt fehlt mir noch ein 32-Bit Bitmap zum Testen und der entsprechende Filter zum Einlesen.

          EDIT:
          Dieses eine 8-Bit Bitmap macht komischerweise Probleme:
          http://www.maxrev.de/files/2006/10/amijdm_140.bmp

          extrahierte Daten:
          Array
          (
          [type] => 19778
          [filesize] => 2206
          [reserved] => 0
          [offset] => 182
          [headersize] => 40
          [width] => 44
          [height] => 46
          [planes] => 1
          [bits] => 8
          [compression] => 0
          [imagesize] => 2024
          [xres] => 3780
          [yres] => 3780
          [ncolor] => 32
          [important] => 32
          [colors] => 256
          [bytes] => 1
          [decal] => 0
          )
          Muss wohl noch eine Sonderlösung her

          EDIT2:
          Ok, hab noch ein paar andere gefunden, die nicht gehen. Auch ein 32-Bit Bitmap dabei mit dem ich dann testen kann. Ich mache aber erst morgen weiter. Halte Euch auf dem Laufenden...
          meine [url=http://www.programmierer-forum.de/php-forum-f1050.htm]PHP Scripte[/url]

          Kommentar


          • #6
            Seit wann gibt es Bitmaps mit 16 Bit Farbtiefe UND Palette?

            Soweit ich weiß können Farbpaletten nur bei den Farbtiefen 1-, 4- und 8-Bit benutzt werden.

            16-Bit benutzt eine Bitmaske, in denen die drei Farbkanäle über 2 Byte verteilt werden; aber niemals eine Farbpalette.
            Bei 24- und 32-Bit wird jeder Farbkanal einzeln in einem Byte gespeichert; auch keine Farbpalette.

            Kommentar


            • #7
              24 Bit und 32 Bit sind im Grunde identisch, der Alphakanal wird bei BMP's nicht genutzt.
              PHP-Code:
                              case 32:
                                  
              $color unpack('V'substr($data$p4) . $vide);
                                  break; 
              Was deinem Code noch fehlt, sind die Kompressionsalgothitmen (RLE4 bzw. RLE8 )

              edit: 8 Bit Palette muss nicht zwangsläufig komplett gefüllt sein. 'biClrUsed' bzw 'biClrImportant' sollte darüber Aufschluss geben. 'biClrUsed' ist 32 bei deinem Beispiel.
              Über 90% aller Gewaltverbrechen passieren innerhalb von 24 Stunden nach dem Konsum von Brot.

              Kommentar


              • #8
                Zitat von Griffith Beitrag anzeigen
                Seit wann gibt es Bitmaps mit 16 Bit Farbtiefe UND Palette?
                Zum dritten Mal: War eine falsche Schlussfolgerung meinerseits :P

                Zitat von lstegelitz Beitrag anzeigen
                24 Bit und 32 Bit sind im Grunde identisch, der Alphakanal wird bei BMP's nicht genutzt.
                Danke werde den Code testen.

                Was deinem Code noch fehlt, sind die Kompressionsalgothitmen (RLE4 bzw. RLE8 )
                Gibt es Grafikprogramme mit denen ich solche Grafiken bauen kann bzw. waren das nicht die, die nur intern von Windows verwendet werden. Hatte da was beiläufig gelesen.

                edit: 8 Bit Palette muss nicht zwangsläufig komplett gefüllt sein. 'biClrUsed' bzw 'biClrImportant' sollte darüber Aufschluss geben. 'biClrUsed' ist 32 bei deinem Beispiel.
                Danke schaue ich gleich mal. Feedback kommt.


                EDIT:
                Also 32-Bit ist genauso wie 24-Bit. Der Alphakanal störte wohl bei der Berechnung der Farbe. Lässt man ihn hingegen weg stimmt alles:
                Code:
                				case 32:
                				case 24:
                					$color = unpack('V', substr($data, $p, 3) . $vide);
                					break;
                Muss ich den Alphakanal berücksichtigen? Weil bei Wikipedia steht folgendes:
                Jeder Farbkanal ist 8 Bit pro Pixel groß; insgesamt ergeben sich 16.777.216 mögliche Farben (8 Bit sind ungenutzt). Einige Programme wie etwa Adobe Photoshop interpretieren die verbleibenden 8 Bits (0xFF000000) als Alphakanal mit 256 möglichen Transparenzstufen. Dies ist jedoch von der Spezifikation nicht vorgesehen.
                Kann Photoshop also transparente 32-Bit Bitmaps erstellen?

                EDIT2:
                Ein paar 24-Bit Bitmaps haben im Header eine filesize gleich offset und die imagesize ist leer. Daher ein Bugfix mit filesize():
                Code:
                	// obtain imagesize
                	if ($meta['imagesize'] < 1) {
                		$meta['imagesize'] = $meta['filesize'] - $meta['offset'];
                		if ($meta['imagesize'] < 1) {
                			$meta['imagesize'] = @filesize($filename) - $meta['offset'];
                			if ($meta['imagesize'] < 1) {
                				trigger_error('imagecreatefrombmp: Can not obtain filesize of ' . $filename . '!', E_USER_WARNING);
                				return false;
                			}
                		}
                	}
                EDIT3:
                Also bei 8-Bit und begrenzter Palette komme ich aktuell nicht weiter. Ich habe die Anzahl der Farben reduziert, sobald biClrUsed gesetzt ist:
                Code:
                	// calculate colors
                	$meta['colors'] = $meta['ncolor'] ? $meta['ncolor'] : pow(2, $meta['bits']);
                Auf die Art lese nun die korrekte Palettengröße aus:
                Code:
                	// read palette
                	$palette = array();
                	if ($meta['colors'] < 16777216 && $meta['bits'] != 16) {
                		$palette = unpack('V' . $meta['colors'], fread($fh, $meta['colors'] * 4));
                	}
                Das Ergebnis bleibt aber schwarz. Ich habe mir mal hier die Farben ausgeben lassen:
                Code:
                				case 8:
                					$color = unpack('n', $vide . substr($data, $p, 1));
                					echo $color[1] . ':';
                					$color[1] = $palette[ $color[1] + 1 ];
                					echo $color[1] . ', ';
                					break;
                Ergebnis (Teilauszug):
                Code:
                26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 2:4278255873, 2:4278255873, 2:4278255873, 2:4278255873, 2:4278255873, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 2:4278255873, 6:4290209603, 17:4288105267, 17:4288105267, 2:4278255873, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 8:4279636996, 20:4282794244, 20:4282794244, 20:4282794244, 20:4282794244, 8:4279636996, 26:0, 26:0, 26:0, 26:0, 26:0, 2:4278255873, 2:4278255873, 2:4278255873, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 2:4278255873, 18:4292051795, 6:4290209603, 17:4288105267, 2:4278255873, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 2:4278255873, 14:4284635918, 9:4291540229, 16:4290160387, 16:4290160387, 16:4290160387, 24:4289305347, 24:4289305347, 14:4284635918, 2:4278255873, 26:0, 26:0, 2:4278255873, 23:4292987432, 9:4291540229, 9:4291540229, 2:4278255873, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 26:0, 2:4278255873, 6:4290209603, 6:4290209603, 19:4289156923, 2:4278255873
                Ich vergleiche mal mit einem 8-Bit Bild das funktioniert. Moment...

                EDIT4:
                Die Palette sieht irgendwie falsch aus, wenn ich davon ausgehe, dass 16.777.215 den höchsten Wert darstellt:
                Code:
                Array
                (
                    [1] => 4294967294
                    [2] => 4292598747
                    [3] => 4278255873
                    [4] => 4278190080
                    [5] => 4293651435
                    [6] => 4294967295
                    [7] => 4290209603
                    [8] => 4294963219
                    [9] => 4279636996
                    [10] => 4291540229
                    [11] => 4294963014
                    [12] => 4294632965
                    [13] => 4294896179
                    [14] => 4293580548
                    [15] => 4284635918
                    [16] => 4292199171
                    [17] => 4290160387
                    [18] => 4288105267
                    [19] => 4292051795
                    [20] => 4289156923
                    [21] => 4282794244
                    [22] => 4287727121
                    [23] => 4292988421
                    [24] => 4292987432
                    [25] => 4289305347
                    [26] => 4292199703
                    [27] => 0
                    [28] => 4278190080
                    [29] => 4278190080
                    [30] => 4278190080
                    [31] => 4278190080
                    [32] => 4278190080
                )
                EDIT5:
                Ich denke mal hier liegt der Hund begraben:
                Code:
                    [xres] => 3780
                    [yres] => 3780
                D.h. biXPelsPerMeter und biYPelsPerMeter. Allerdings habe ich keine Ahnung wie ich die anwenden muss...

                Oder gibt es wieder gar keine Palette ^^

                EDIT6:
                Bei einem 1-Bit Bild genau das gleiche Problem:
                Code:
                Array
                (
                    [type] => 19778
                    [filesize] => 270254
                    [reserved] => 0
                    [offset] => 62
                    [headersize] => 40
                    [width] => 1238
                    [height] => 1732
                    [planes] => 1
                    [bits] => 1
                    [compression] => 0
                    [imagesize] => 270192
                    [xres] => 5905
                    [yres] => 5905
                    [ncolor] => 2
                    [important] => 2
                    [colors] => 2
                    [bytes] => 0.125
                    [decal] => 1.25
                )
                meine [url=http://www.programmierer-forum.de/php-forum-f1050.htm]PHP Scripte[/url]

                Kommentar


                • #9
                  EDIT5:
                  Ich denke mal hier liegt der Hund begraben:
                  Code:
                      [xres] => 3780
                      [yres] => 3780
                  D.h. biXPelsPerMeter und biYPelsPerMeter. Allerdings habe ich keine Ahnung wie ich die anwenden muss...
                  Die Angaben sind in "Pixel pro Meter". Für die handeslübliche Auflösung "Pixel pro Zoll" (DPI, dots per inch) rechnest du einfach um, z.B.:
                  3780 / 100 * 2.54 = ~96
                  5905 / 100 * 2.54 = ~150
                  (Ein inch sind ungefähr 2.54 cm)

                  Ich glaube eher, dein Hund liegt hier begraben:
                  PHP-Code:
                      $meta['bytes'] = $meta['bits'] / 8;
                      
                  $meta['decal'] = - (* (($meta['width'] * $meta['bytes'] / 4)- floor($meta['width'] * $meta['bytes'] / 4)));
                      if (
                  $meta['decal'] == 4) {
                          
                  $meta['decal'] = 0;
                      } 
                  Ein Farbwert (egal ob per Index oder per RGB Wert angegeben) kann nicht kleiner als eine Byte sein, daher ist auch die Folgenberechnung des Paddings verkehrt.

                  "byte" ist 1 für 1,2,4,8 Bit Farbtiefe
                  "byte" ist 2 für 16 Bit Farbtiefe
                  "byte" ist 3 für 24 Bit Farbtiefe
                  "byte" ist 4 für 32 Bit Farbtiefe

                  "decal" ist 4 - ((width * "byte") % 4)


                  Die Datei sieht auch etwas seltsam aus:
                  Array
                  (
                  [type] => 19778
                  [filesize] => 270254
                  [reserved] => 0
                  [offset] => 62
                  [headersize] => 40
                  [width] => 1238
                  [height] => 1732
                  [planes] => 1
                  [bits] => 1
                  [compression] => 0
                  [imagesize] => 270192
                  [xres] => 5905
                  [yres] => 5905
                  [ncolor] => 2
                  [important] => 2
                  [colors] => 2
                  [bytes] => 0.125
                  [decal] => 1.25
                  )
                  Da compression == BI_RGB(0) ist, berechnet sich die Größe der Bilddaten.
                  padding: 2 byte (width % 4)
                  1240 * 1732 * 1 / 8 ( (width + padding) * height * bits / 8 ) = 268460

                  Da ensteht genau eine Spalte Differenz: 270192 - 268460 = 1732

                  Wie groß ist die Datei denn wirklich (physisch)? Bzw. was sagt ein anderes Bildbearbeitungsprogramm bezüglich Größe?
                  Über 90% aller Gewaltverbrechen passieren innerhalb von 24 Stunden nach dem Konsum von Brot.

                  Kommentar


                  • #10
                    Zitat von lstegelitz Beitrag anzeigen
                    Ein Farbwert (egal ob per Index oder per RGB Wert angegeben) kann nicht kleiner als eine Byte sein, daher ist auch die Folgenberechnung des Paddings verkehrt.

                    "byte" ist 1 für 1,2,4,8 Bit Farbtiefe
                    "byte" ist 2 für 16 Bit Farbtiefe
                    "byte" ist 3 für 24 Bit Farbtiefe
                    "byte" ist 4 für 32 Bit Farbtiefe

                    "decal" ist 4 - ((width * "byte") % 4)
                    Ich habs so getestet:
                    PHP-Code:
                        // set bytes
                        
                    switch ($meta['bits']) {
                            case 
                    32:
                                
                    $meta['bytes'] = 4;
                                break;
                            case 
                    24:
                                
                    $meta['bytes'] = 3;
                                break;
                            case 
                    16:
                                
                    $meta['bytes'] = 2;
                                
                    // read additional 16bit header
                                
                    $meta += unpack('VrMask/VgMask/VbMask'fread($fh12));
                                break;
                            default:
                                
                    $meta['bytes'] = 1;
                        }
                        
                    // set padding
                        
                    $meta['decal'] = - (($meta['width'] * $meta['bytes']) % 4); 
                    Dann geht aber gar kein Bild mehr

                    Scheinbar muss es manchmal "leere" Rückgaben geben. Leer schein mir dann die Standardfarbe aus der Palette zu sein, die sich durch unpack('n', chr(0)) ergibt. Das gilt übrigens für 8, 4 und 1 Bit. Ich hatte nämlich erst versucht einen Error zu triggern, wenn $part leer ist:
                    PHP-Code:
                                    case 8:
                                        if (!(
                    $part substr($data$p1))) {
                                            
                    trigger_error($errorE_USER_WARNING);
                                            return 
                    $im;
                                        }
                                        
                    $color unpack('n'$vide $part);
                                        
                    $color[1] = $palette$color[1] + ];
                                        break; 
                    Dabei lief er schon nach kurzer Zeit in den Fehler und lieferte nur noch wenige Zeilen von dem Bild aus.

                    Zitat von lstegelitz Beitrag anzeigen
                    Die Datei sieht auch etwas seltsam aus:

                    Da compression == BI_RGB(0) ist, berechnet sich die Größe der Bilddaten.
                    padding: 2 byte (width % 4)
                    1240 * 1732 * 1 / 8 ( (width + padding) * height * bits / 8 ) = 268460

                    Da ensteht genau eine Spalte Differenz: 270192 - 268460 = 1732

                    Wie groß ist die Datei denn wirklich (physisch)? Bzw. was sagt ein anderes Bildbearbeitungsprogramm bezüglich Größe?
                    Die physische Größe stimmt laut filesize() mit $meta['filesize'] überein. Laut Paint/Windows/Photoshop hat das Bild die folgenden Angaben:
                    1238x1732 Pixel, 270.254 Bytes, 150x150 Punkte pro Zoll

                    Hier der Link zu dem besagten Bild:
                    http://www.maxrev.de/files/2006/10/p...and_bild_1.bmp

                    Ein anderes 1-Bit Bild mit diesen Angaben geht übrigens problemlos:
                    PHP-Code:
                    Array
                    (
                        [
                    type] => 19778
                        
                    [filesize] => 139838
                        
                    [reserved] => 0
                        
                    [offset] => 62
                        
                    [headersize] => 40
                        
                    [width] => 1218
                        
                    [height] => 896
                        
                    [planes] => 1
                        
                    [bits] => 1
                        
                    [compression] => 0
                        
                    [imagesize] => 139776
                        
                    [xres] => 0
                        
                    [yres] => 0
                        
                    [ncolor] => 0
                        
                    [important] => 0
                        
                    [bytes] => 0.125
                        
                    [decal] => 3.75
                        
                    [colors] => 2

                    Daher glaube ich, dass es irgendwas mit der Palette zu tun haben muss.

                    EDIT:
                    Diese Formel habe ich gefunden (von hier: http://en.wikipedia.org/wiki/Windows...#Pixel_storage ):
                    Using info from the article, here's a good formula for bmp filesize in bytes (when bits-per-pixel < 16):
                    54 + 4*(num_colors) + 4*ceil(width * bits_per_pixel / 32.0)*height
                    Das habe ich getestet und es resultiert das richtige Ergebnis:
                    PHP-Code:
                        $meta['calculated_filesize'] = 54 $meta['colors'] + ceil($meta['width'] * $meta['bits'] / 32) * $meta['height']; 
                    meine [url=http://www.programmierer-forum.de/php-forum-f1050.htm]PHP Scripte[/url]

                    Kommentar


                    • #11
                      Ich hab dafür nur eine mögliche Antwort.

                      Bei 1, 2 und 4 Bit Farbtiefe wird ein Index in die Farbtabelle aus ebenso vielen Bits erstellt (Sonderfall: bei 8 Bit Farbtiefe besteht der Index aus 8 Bit = 1 Byte). Was dann als "Zeilenbreite" herauskommt, muss auf eine 4-Byte Grenze ausgerichtet werden.

                      Beispiel 1 Bit:
                      Breite des Bildes 1238 Pixel, jeder Pixel hat 1 bit für den Index (kann 0 oder 1 werden), dadurch hat eine Zeile 154.75 Byte (1238 / 8 ), aufgerundet auf 4-Byte Grenze: 156 (1.25 Byte overhead)
                      156 * 1732 = 270192

                      JETZT macht dein "krummer" Offset tatsächlich Sinn und meine Aussage ist damit falsch!

                      Ist lange her, das ich mich mit dem BMP Format beschäftigt hab
                      Über 90% aller Gewaltverbrechen passieren innerhalb von 24 Stunden nach dem Konsum von Brot.

                      Kommentar


                      • #12
                        Jo stimmt. Jetzt verstehe ich nach Deiner Erklärung auch den Satz aus Wikipedia ^^
                        Jede Bildzeile ist durch rechtsseitiges Auffüllen mit Nullen auf ein ganzzahliges Vielfaches von 4 Bytes ausgerichtet. Das Format der Pixel ist in den Farbmasken definiert. Bei 16 bpp werden nur die beiden niederwertigen Bytes der Farbmasken berücksichtigt.
                        Ich habe leider gar kein Grundlagenwissen in Sachen Binärdaten und Bit-Operatoren, sonst wüsste ich vermutlich eher wie man hier mit Try & Error das Problem mit den Paletten erkennen könnte.

                        Aber ich bleibe jetzt mal bei den zwei 1-Bit Bildern. Das erste was funktioniert hat diese Palette:
                        PHP-Code:
                        Array
                        (
                            [
                        1] => 0
                            
                        [2] => 16777215

                        Ziemlich offensichtlich schwarz und weiß.

                        Das nicht geht hat diese Palette:
                        PHP-Code:
                        Array
                        (
                            [
                        1] => 4278190080
                            
                        [2] => 4294967295

                        Gehe ich nun hin und übergebe manuell die Farbpalette des korrekten Bildes, dann läuft es auch beim zweiten Bild. Daraus schlussfolgere ich nun, dass die Farbpalette im Falle von biClrUsed anders hinterlegt wird und so nicht ausgelesen werden kann:
                        PHP-Code:
                                $palette unpack('V' $meta['colors'], fread($fh$meta['colors'] * 4)); 
                        Leider kann ich bei Wikipedia bzw. der Microsoft Doku nichts finden, was auf eine unterschiedliche Speicherungsart hinweist. Mal sehen was die Google-Suche noch so ausspuckt.

                        EDIT:
                        Auf Grund dieser Aussage habe ich schon mal die Bedingung geändert:
                        As mentioned above, the color palette is not used when the bitmap is 16-bit or higher; there are no palette bytes in those BMP files.
                        PHP-Code:
                            if ($meta['bits'] < 16) {
                                
                        $palette unpack('V' $meta['colors'], fread($fh$meta['colors'] * 4));
                            } 
                        OS/2 V1 kann es ja denke ich nicht sein, weil wir z.B. biXPelsPerMeter erhalten haben, die in der Version nicht verfügbar sind:
                        The number of entries in the palette is either 2n or a smaller number specified in the header (in the OS/2 V1 format, only the full-size palette is supported). Each entry contains four bytes, except in the case of the OS/2 V1 versions, in which case there are only three bytes per entry
                        Ok dazu wohl die Bestätigung:
                        You must be sure to check the Size field of the bitmap header to know if you are reading 3-byte or 4-byte color palette elements. A Size value of 12 indicates an OS/2 1.x (or possibly a Windows 2.x) BMP file with 3-byte elements. Larger numbers, such as 64, indicate later versions of BMP, which all use 4-byte color palette elements.
                        Nur wenn der Header 12 Bytes groß ist, muss man die Palette im 3 Byte Raster auslesen.

                        Das gleiche gilt für alte Windows Bitmap Definitionsversionen:
                        You must be sure to check the Size field of the bitmap header to know if you are reading 3-byte or 4-byte color palette elements. A Size value of 12 indicates a Windows 2.x (or possibly an OS/2 1.x) BMP file with 3-byte elements. Larger numbers (such as 40 and 10 indicate later versions of BMP, which all use 4-byte color palette elements.
                        EDIT2:
                        Also ich bin mal die komplette 8-Bit Datei durchgegangen, um die Palette zu finden, aber es wird nichts ausgegeben:
                        PHP-Code:
                            echo '<pre>';
                            for (
                        $i=0;$i<=$meta['filesize'];$i++) {
                                
                        fseek($fh$i);
                                
                        $palette unpack('V' $meta['colors'], fread($fh$meta['colors'] * 4));
                                
                        $valid true;
                                foreach (
                        $palette as $color) {
                                    if (
                        $color 16777215) {
                                        
                        $valid false;
                                        break;
                                    }
                                }
                                if (
                        $valid) {
                                    echo 
                        $i '. ';
                                    
                        print_r($palette);
                                }
                            }
                            echo 
                        '</pre>'
                        D.h. es war immer mindestens ein Wert der ausgelesenen Daten größer als 16777215 und damit kann es sich nicht um eine Palette gehandelt haben.

                        EDIT3:
                        Vielleicht für später mal interessant:
                        If your file type is "BM", then you must now read the Size field of the bitmap header to determine the version of the file. Size will be 12 for Windows 2.x BMP and OS/2 1.x BMP, 40 for Windows 3.x and Windows NT BMP, 12 to 64 for OS/2 2.x BMP, and 108 for Windows 4.x BMP. A Windows NT BMP file will always have a Compression value of 3; otherwise, it is read as a Windows 3.x BMP file.

                        Note that the only difference between Windows 2.x BMP and OS/2 1.x BMP is the data type of the Width and Height fields. For Windows 2.x, they are signed shorts and for OS/2 1.x, they are unsigned shorts. Windows 3.x, Windows NT, and OS/2 2.x BMP files only vary in the number of fields in the bitmap header and in the interpretation of the Compression field.
                        EDIT4:
                        Kann es sein, dass Bilder mit <= 256 Farben gar keine Palette haben, sondern erwarten, dass die öffnende Software eine Palette zur Verfügung stellt?! Ich habe hier das gefunden:
                        Code:
                           // Get the DIBSection's color table
                           GetDIBColorTable( hMemDC, 0, 256, rgb );
                           // Create a palette from the color tabl
                           pLogPal = (LOGPALETTE *)malloc( sizeof(LOGPALETTE) + (256*sizeof(PALETTEENTRY)) );
                           pLogPal->palVersion = 0x300;
                           pLogPal->palNumEntries = 256;
                           for(i=0;i<256;i++)
                           {
                             pLogPal->palPalEntry[i].peRed = rgb[i].rgbRed;
                             pLogPal->palPalEntry[i].peGreen = rgb[i].rgbGreen;
                             pLogPal->palPalEntry[i].peBlue = rgb[i].rgbBlue;
                             pLogPal->palPalEntry[i].peFlags = 0;
                           }
                           *phPalette = CreatePalette( pLogPal );
                        Ich kann kein C, aber das ließt sich irgendwie so, also würde hier eine Palette "on-the-fly" generiert?!

                        EDIT5:
                        Ne da muss eine Palette sein. Wenn ich nämlich die Palette nicht auslese und manuell die gewollte Palette übergebe, wird das Bild versetzt aufgebaut:
                        http://www.maxrev.de/img/cache/pruef...1271706058.jpg (links schwarzer Streifen: nicht im Original vorhanden)

                        EDIT6:
                        Noch was um Bitmaps in C einzulesen:
                        Code:
                            if(bpp == 8) 							// load the color palette for 8 bits per pixel
                        
                        	{
                        		numColours = 1 << bpp;				// calculate the number of available colours
                        
                        		colours = new RGBQuad[numColours];					
                            	fread(colours, sizeof(RGBQuad), numColours, in);	// read in the color palette
                        
                            }
                        Was genau RGBQuad hier macht verstehe ich leider nicht.
                        meine [url=http://www.programmierer-forum.de/php-forum-f1050.htm]PHP Scripte[/url]

                        Kommentar


                        • #13
                          Juhu ich habs.. uff das war ja was ^^

                          Und zwar kann der Paletten-Farbwert auch negativ sein. D.h. der Format-Operator V ist falsch. Stattdessen muss l (kleines L) zum Einsatz kommen.

                          Ich bin darauf gekommen als ich einfach mal alle verfügbaren Format-Typen durchgearbeitet habe und dabei dann diese Resultate erhielt:
                          PHP-Code:
                          n. Array
                          (
                              [
                          1] => 0
                              
                          [2] => 255
                          )
                          N. Array
                          (
                              [
                          1] => 255
                              
                          [2] => 4294967295
                          )
                          v. Array
                          (
                              [
                          1] => 0
                              
                          [2] => 65280
                          )
                          V. Array
                          (
                              [
                          1] => 4278190080
                              
                          [2] => 4294967295
                          )
                          i. Array
                          (
                              [
                          1] => -16777216
                              
                          [2] => -1
                          )
                          I. Array
                          (
                              [
                          1] => -16777216
                              
                          [2] => -1
                          )
                          l. Array
                          (
                              [
                          1] => -16777216
                              
                          [2] => -1
                          )
                          L. Array
                          (
                              [
                          1] => 4278190080
                              
                          [2] => 4294967295

                          Auf Basis dessen lese ich die Palette nun wie folgt aus:
                          PHP-Code:
                              // read palette
                              
                          $palette = array();
                              if (
                          $meta['bits'] < 16) {
                                  
                          $palette unpack('l' $meta['colors'], fread($fh$meta['colors'] * 4));
                              }
                              if (
                          $palette[1] < 0) {
                                  foreach (
                          $palette as $i => $color) {
                                      
                          $palette[$i] = $color 16777216;
                                  }
                              } 
                          Eine bessere Variante ist mir nicht eingefallen.

                          Hier mein Ergebnis:
                          http://www.programmierer-forum.de/fu...ft-t143137.htm
                          meine [url=http://www.programmierer-forum.de/php-forum-f1050.htm]PHP Scripte[/url]

                          Kommentar


                          • #14
                            Sauber, Glückwunsch

                            Postest du dann mal den kompletten Code, könnte man in die Wiki aufnehmen oder sowas in der Art.

                            Noch ein Nachtrag zum C Code
                            EDIT4:
                            Kann es sein, dass Bilder mit <= 256 Farben gar keine Palette haben, sondern erwarten, dass die öffnende Software eine Palette zur Verfügung stellt?! Ich habe hier das gefunden:
                            Code:
                            Code:
                               // Get the DIBSection's color table
                               GetDIBColorTable( hMemDC, 0, 256, rgb );
                               // Create a palette from the color tabl
                               pLogPal = (LOGPALETTE *)malloc( sizeof(LOGPALETTE) + (256*sizeof(PALETTEENTRY)) );
                               pLogPal->palVersion = 0x300;
                               pLogPal->palNumEntries = 256;
                               for(i=0;i<256;i++)
                               {
                                 pLogPal->palPalEntry[i].peRed = rgb[i].rgbRed;
                                 pLogPal->palPalEntry[i].peGreen = rgb[i].rgbGreen;
                                 pLogPal->palPalEntry[i].peBlue = rgb[i].rgbBlue;
                                 pLogPal->palPalEntry[i].peFlags = 0;
                               }
                               *phPalette = CreatePalette( pLogPal );
                            Es wird eine "Roh"palette ausgelesen (bzw. kopiert), der Aufruf von CreatePalette kommt aus der Windows API und bereitet die Palette so auf, das ein DC damit was anfangen kann (DC=device Context, z.B. Bildschirm). Die nennen die gespeicherten Farbdaten auch "color table".

                            Gelesen wird die Palette mit diesem Code:
                            Code:
                                if(bpp == 8) 							// load the color palette for 8 bits per pixel
                            
                            	{
                            		numColours = 1 << bpp;				// calculate the number of available colours
                            
                            		colours = new RGBQuad[numColours];					
                                	fread(colours, sizeof(RGBQuad), numColours, in);	// read in the color palette
                            
                                }
                            RGBQuad ist eine Struktur, ein komplexer Datentyp (sowas wie eine Klasse ohne Funktionen und ohne Zugriffsschutz.. alle Variablen einer Struktur sind public). In Etwa so:
                            Code:
                            struct {
                              BYTE rgbRed;
                              BYTE rgbGreen;
                              BYTE rgbBlue;
                              BYTE rgbReserved;
                            } RGBQuad;
                            Code:
                            colours = new RGBQuad[numColours];
                            erzeugt ein Array von Typ RGBQuad mit numColours Einträgen.
                            Über 90% aller Gewaltverbrechen passieren innerhalb von 24 Stunden nach dem Konsum von Brot.

                            Kommentar


                            • #15
                              Bei RGBQuad habe ich nicht verstanden, warum numColours = Anzahl der Farben die passenden Farben als Array erhalten kann. Wenn ein Bild sagen wir mal 256 Farben hat, woher will denn RGBQuad wissen welche das sein können, wenn doch nur die Summe der Farben übertragen wird.

                              Die fertige Funktion habe ich in meinem letzten Beitrag verlinkt. Bedien Dich ^^

                              Jetzt fehlt im Grunde noch imagebmp. Dazu habe ich die Funktion gefunden:
                              http://www.programmierer-forum.de/im...16.htm#2367838

                              8 und 24-Bit ohne Kompression habe ich getestet und für gut befunden
                              meine [url=http://www.programmierer-forum.de/php-forum-f1050.htm]PHP Scripte[/url]

                              Kommentar

                              Lädt...
                              X