IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Calcul scientifique Python Discussion :

Generer une image bitmap 24 bits avec PIL


Sujet :

Calcul scientifique Python

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 206
    Points : 79
    Points
    79
    Par défaut Generer une image bitmap 24 bits avec PIL
    Bonjour à tous

    Je suis en train de réaliser un programme qui génère un code barre et l'exporte vers excel via pyexcelerator.Hélas, je dois faire face à quelques problèmes. En effet, je sauvegarde une image bmp de cette façon:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    self.im.save("test.bmp","BMP")
    Ensuite, je renvoie l'image vers excel de cette manière(dans l'hypothèse ou je viens d'enregistrer un code barre "test"):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        def export(self):
            from pyexcelerator import *
            w = Workbook()
            ws = w.add_sheet('Image')
            ws.insert_bitmap('test.bmp', 0, 0)
            w.save('image.xls')
    Le shell me sort alors le message d'erreur suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Exception in Tkinter callback
    Traceback (most recent call last):
      File "C:\Python26\lib\lib-tk\Tkinter.py", line 1410, in __call__
        return self.func(*args)
      File "C:\Python26\structure.py", line 411, in export
        ws.insert_bitmap('test.bmp', 0, 0)
      File "C:\Python26\lib\site-packages\pyExcelerator\Worksheet.py", line 1132, in insert_bitmap
        bmp = Bitmap.ImDataBmpRecord(filename)
      File "C:\Python26\lib\site-packages\pyExcelerator\Bitmap.py", line 298, in __init__
        self.width, self.height, self.size, data = _process_bitmap(filename)
      File "C:\Python26\lib\site-packages\pyExcelerator\Bitmap.py", line 272, in _process_bitmap
        raise Exception("bitmap isn't a 24bit true color bitmap.")
    Exception: bitmap isn't a 24bit true color bitmap.
    Voici le contenu de "Bitmap.py" de la librairie pyexcelerator:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    #!/usr/bin/env python
    # -*- coding: windows-1251 -*-
     
    #  Copyright (C) 2005 Roman V. Kiseliov
     
    #  Portions are Copyright (c) 2004 Evgeny Filatov <fufff@users.sourceforge.net>
     
    #  Portions are Copyright (c) 2002-2004 John McNamara (Perl Spreadsheet::WriteExcel)
     
    #  All rights reserved.
     
    # 
    #  Redistribution and use in source and binary forms, with or without
    #  modification, are permitted provided that the following conditions
    #  are met:
    # 
    #  1. Redistributions of source code must retain the above copyright
    #     notice, this list of conditions and the following disclaimer.
    # 
    #  2. Redistributions in binary form must reproduce the above copyright
    #     notice, this list of conditions and the following disclaimer in
    #     the documentation and/or other materials provided with the
    #     distribution.
    # 
    #  3. All advertising materials mentioning features or use of this
    #     software must display the following acknowledgment:
    #     "This product includes software developed by
    #      Roman V. Kiseliov <roman@kiseliov.ru>."
    # 
    #  4. Redistributions of any form whatsoever must retain the following
    #     acknowledgment:
    #     "This product includes software developed by
    #      Roman V. Kiseliov <roman@kiseliov.ru>."
    # 
    #  THIS SOFTWARE IS PROVIDED BY Roman V. Kiseliov ``AS IS'' AND ANY
    #  EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    #  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    #  PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL Roman V. Kiseliov OR
    #  ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    #  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    #  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    #  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    #  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
    #  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    #  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
    #  OF THE POSSIBILITY OF SUCH DAMAGE.
     
     
    __rev_id__ = """$Id: Bitmap.py,v 1.4 2005/07/20 07:24:11 rvk Exp $"""
     
     
    from BIFFRecords import BiffRecord
    from struct import *
     
     
    def _size_col(sheet, col):
        return sheet.col_width(col)
     
     
    def _size_row(sheet, row):
        return sheet.row_height(row)     
     
     
    def _position_image(sheet, row_start, col_start, x1, y1, width, height):
        """Calculate the vertices that define the position of the image as required by
        the OBJ record.
     
                 +------------+------------+
                 |     A      |      B     |
           +-----+------------+------------+
           |     |(x1,y1)     |            |
           |  1  |(A1)._______|______      |
           |     |    |              |     |
           |     |    |              |     |
           +-----+----|    BITMAP    |-----+
           |     |    |              |     |
           |  2  |    |______________.     |
           |     |            |        (B2)|
           |     |            |     (x2,y2)|
           +---- +------------+------------+
     
        Example of a bitmap that covers some of the area from cell A1 to cell B2.
     
        Based on the width and height of the bitmap we need to calculate 8 vars:
            col_start, row_start, col_end, row_end, x1, y1, x2, y2.
        The width and height of the cells are also variable and have to be taken into
        account.
        The values of col_start and row_start are passed in from the calling
        function. The values of col_end and row_end are calculated by subtracting
        the width and height of the bitmap from the width and height of the
        underlying cells.
        The vertices are expressed as a percentage of the underlying cell width as
        follows (rhs values are in pixels):
     
               x1 = X / W *1024
               y1 = Y / H *256
               x2 = (X-1) / W *1024
               y2 = (Y-1) / H *256
     
               Where:  X is distance from the left side of the underlying cell
                       Y is distance from the top of the underlying cell
                       W is the width of the cell
                       H is the height of the cell
     
        Note: the SDK incorrectly states that the height should be expressed as a
        percentage of 1024.
     
        col_start  - Col containing upper left corner of object
        row_start  - Row containing top left corner of object
        x1  - Distance to left side of object
        y1  - Distance to top of object
        width  - Width of image frame
        height  - Height of image frame
        
        """
        # Adjust start column for offsets that are greater than the col width
        while x1 >= _size_col(sheet, col_start):
            x1 -= _size_col(sheet, col_start)
            col_start += 1
        # Adjust start row for offsets that are greater than the row height
        while y1 >= _size_row(sheet, row_start):
            y1 -= _size_row(sheet, row_start)
            row_start += 1
        # Initialise end cell to the same as the start cell
        row_end = row_start   # Row containing bottom right corner of object
        col_end = col_start   # Col containing lower right corner of object
        width = width + x1 - 1
        height = height + y1 - 1
        # Subtract the underlying cell widths to find the end cell of the image
        while (width >= _size_col(sheet, col_end)):
            width -= _size_col(sheet, col_end)
            col_end += 1
        # Subtract the underlying cell heights to find the end cell of the image
        while (height >= _size_row(sheet, row_end)):
            height -= _size_row(sheet, row_end)
            row_end += 1
        # Bitmap isn't allowed to start or finish in a hidden cell, i.e. a cell
        # with zero height or width.
        if ((_size_col(sheet, col_start) == 0) or (_size_col(sheet, col_end) == 0)
                or (_size_row(sheet, row_start) == 0) or (_size_row(sheet, row_end) == 0)):
            return
        # Convert the pixel values to the percentage value expected by Excel
        x1 = float(x1) / _size_col(sheet, col_start) * 1024
        y1 = float(y1) / _size_row(sheet, row_start) * 256
        # Distance to right side of object
        x2 = float(width) / _size_col(sheet, col_end) * 1024
        # Distance to bottom of object
        y2 = float(height) / _size_row(sheet, row_end) * 256
        return (col_start, x1, row_start, y1, col_end, x2, row_end, y2)
     
     
    class ObjBmpRecord(BiffRecord):
        _REC_ID = 0x005D    # Record identifier
     
        def __init__(self, row, col, sheet, im_data_bmp, x, y, scale_x, scale_y):
            # Scale the frame of the image.
            width = im_data_bmp.width * scale_x
            height = im_data_bmp.height * scale_y
     
            # Calculate the vertices of the image and write the OBJ record
            col_start, x1, row_start, y1, col_end, x2, row_end, y2 = _position_image(sheet, row, col, x, y, width, height)
     
            """Store the OBJ record that precedes an IMDATA record. This could be generalise
            to support other Excel objects.
     
            """
            cObj = 0x0001      # Count of objects in file (set to 1)
            OT = 0x0008        # Object type. 8 = Picture
            id = 0x0001        # Object ID
            grbit = 0x0614     # Option flags
            colL = col_start    # Col containing upper left corner of object
            dxL = x1            # Distance from left side of cell
            rwT = row_start     # Row containing top left corner of object
            dyT = y1            # Distance from top of cell
            colR = col_end      # Col containing lower right corner of object
            dxR = x2            # Distance from right of cell
            rwB = row_end       # Row containing bottom right corner of object
            dyB = y2            # Distance from bottom of cell
            cbMacro = 0x0000    # Length of FMLA structure
            Reserved1 = 0x0000  # Reserved
            Reserved2 = 0x0000  # Reserved
            icvBack = 0x09      # Background colour
            icvFore = 0x09      # Foreground colour
            fls = 0x00          # Fill pattern
            fAuto = 0x00        # Automatic fill
            icv = 0x08          # Line colour
            lns = 0xff          # Line style
            lnw = 0x01          # Line weight
            fAutoB = 0x00       # Automatic border
            frs = 0x0000        # Frame style
            cf = 0x0009         # Image format, 9 = bitmap
            Reserved3 = 0x0000  # Reserved
            cbPictFmla = 0x0000 # Length of FMLA structure
            Reserved4 = 0x0000  # Reserved
            grbit2 = 0x0001     # Option flags
            Reserved5 = 0x0000  # Reserved
     
            data = pack("<L", cObj)
            data += pack("<H", OT)
            data += pack("<H", id)
            data += pack("<H", grbit)
            data += pack("<H", colL)
            data += pack("<H", dxL)
            data += pack("<H", rwT)
            data += pack("<H", dyT)
            data += pack("<H", colR)
            data += pack("<H", dxR)
            data += pack("<H", rwB)
            data += pack("<H", dyB)
            data += pack("<H", cbMacro)
            data += pack("<L", Reserved1)
            data += pack("<H", Reserved2)
            data += pack("<B", icvBack)
            data += pack("<B", icvFore)
            data += pack("<B", fls)
            data += pack("<B", fAuto)
            data += pack("<B", icv)
            data += pack("<B", lns)
            data += pack("<B", lnw)
            data += pack("<B", fAutoB)
            data += pack("<H", frs)
            data += pack("<L", cf)
            data += pack("<H", Reserved3)
            data += pack("<H", cbPictFmla)
            data += pack("<H", Reserved4)
            data += pack("<H", grbit2)
            data += pack("<L", Reserved5)
     
            self._rec_data = data
     
    def _process_bitmap(bitmap):
        """Convert a 24 bit bitmap into the modified internal format used by Windows.
        This is described in BITMAPCOREHEADER and BITMAPCOREINFO structures in the
        MSDN library.
     
        """
        # Open file and binmode the data in case the platform needs it.
        fh = file(bitmap, "rb")
        try:
            # Slurp the file into a string.
            data = fh.read()
        finally:
            fh.close()
        # Check that the file is big enough to be a bitmap.
        if len(data) <= 0x36:
            raise Exception("bitmap doesn't contain enough data.")
        # The first 2 bytes are used to identify the bitmap.
        if (data[:2] != "BM"):
            raise Exception("bitmap doesn't appear to to be a valid bitmap image.")
        # Remove bitmap data: ID.
        data = data[2:]
        # Read and remove the bitmap size. This is more reliable than reading
        # the data size at offset 0x22.
        #
        size = unpack("<L", data[:4])[0]
        size -=  0x36   # Subtract size of bitmap header.
        size +=  0x0C   # Add size of BIFF header.
        data = data[4:]
        # Remove bitmap data: reserved, offset, header length.
        data = data[12:]
        # Read and remove the bitmap width and height. Verify the sizes.
        width, height = unpack("<LL", data[:8])
        data = data[8:]
        if (width > 0xFFFF):
            raise Exception("bitmap: largest image width supported is 65k.")
        if (height > 0xFFFF):
            raise Exception("bitmap: largest image height supported is 65k.")
        # Read and remove the bitmap planes and bpp data. Verify them.
        planes, bitcount = unpack("<HH", data[:4])
        data = data[4:]
        if (bitcount != 24):
            raise Exception("bitmap isn't a 24bit true color bitmap.")
        if (planes != 1):
            raise Exception("bitmap: only 1 plane supported in bitmap image.")
        # Read and remove the bitmap compression. Verify compression.
        compression = unpack("<L", data[:4])[0]
        data = data[4:]
        if (compression != 0):
            raise Exception("bitmap: compression not supported in bitmap image.")
        # Remove bitmap data: data size, hres, vres, colours, imp. colours.
        data = data[20:]
        # Add the BITMAPCOREHEADER data
        header = pack("<LHHHH", 0x000c, width, height, 0x01, 0x18)
        data = header + data
        return (width, height, size, data)
     
     
    class ImDataBmpRecord(BiffRecord):
        _REC_ID = 0x007F
     
        def __init__(self, filename):
            """Insert a 24bit bitmap image in a worksheet. The main record required is
            IMDATA but it must be proceeded by a OBJ record to define its position.
     
            """
            BiffRecord.__init__(self)
     
            self.width, self.height, self.size, data = _process_bitmap(filename)
            # Write the IMDATA record to store the bitmap data
            cf = 0x09
            env = 0x01
            lcb = self.size
            self._rec_data = pack("<HHL", cf, env, lcb) + data
    Je pense que la solution serait de générer des images en 24 bits avec pil, mais je ne sais pas comment l'imposer. Avez-vous une idée?

    Merci d'avance

  2. #2
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Tu peux peut-être convertir ton image avant avec PIL ? ll ne me semble pas que tu puisses modifier dans Bitmap.py la lecture (même pas sûr qu'il lise effectivement le fichier en entier), mais quoique tu fasses, tu vas en réalité ouvrir l'image, la sauvegarder en 24bits et l'insérer.

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 206
    Points : 79
    Points
    79
    Par défaut
    Salut Mathieu et merci de ta réponse

    C'est effectivement, la bonne, il faut qu'au moment de la création de l'image je choisisse le mode "RGB" et non pas le mode "1" (qui correspond au mode monochrome comme je l'avais fait). Le souci c'est qu'en modifiant le mode, il faut aussi que je modifie tout le reste parce que ça me sortait une image complètement différente.

    Heureusement je n'ai pas eu à le faire car j'ai réussi à faire ce que je voulais grâce à une autre librairie, win32com, qui gère plus de formats que pyexcelerator. Mon problème est donc résolu

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [OpenGl ES] Retourner une image bitmap (avec VBO ?)
    Par me.in.worst dans le forum OpenGL
    Réponses: 2
    Dernier message: 18/09/2009, 11h15
  2. Convertir une image BMP 8 bits en BMP 24 bits
    Par SauCisS dans le forum Bibliothèques
    Réponses: 17
    Dernier message: 23/03/2005, 09h51
  3. Réponses: 6
    Dernier message: 22/12/2004, 11h00
  4. generer une image bitmap a partir d'une scene OGL
    Par FreshLog dans le forum OpenGL
    Réponses: 4
    Dernier message: 01/07/2003, 11h29
  5. Lecture d'une image bitmap
    Par Geronimo dans le forum x86 32-bits / 64-bits
    Réponses: 18
    Dernier message: 28/06/2002, 12h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo