def processCombinedImg(data, meta_fname, combinedImageUri, combinedImageShortUri, combinedImageObject):
            # make sure lib and type info for the combined image are present
            assert combinedImageObject.lib, combinedImageObject.type

            # see if we have cached the contents (json) of this .meta file
            cacheId = "imgcomb-%s" % meta_fname
            imgDict = self._cache.read(cacheId, meta_fname)
            if imgDict == None:
                mfile = open(meta_fname)
                imgDict = simplejson.loads(mfile.read())
                mfile.close()
                self._cache.write(cacheId, imgDict)

            # now loop through the dict structure from the .meta file
            for imagePath, imageSpec_ in imgDict.items():
                # sort of like this: imagePath : [width, height, type, combinedUri, off-x, off-y]

                imageObject = ImgInfoFmt(imageSpec_) # turn this into an ImgInfoFmt object, to abstract from representation in .meta file and loader script

                # have to normalize the uri's from the meta file
                #imageUri = normalizeImgUri(imagePath, combinedImageUri, imageObject.mappedId)
                imageUri = imagePath

                ## replace lib uri with lib namespace in imageUri
                imageShortUri = extractAssetPart(librespath, imageUri)
                imageShortUri = Path.posifyPath(imageShortUri)

                # now put all elements of the image object together
                imageObject.mappedId = combinedImageShortUri        # correct the mapped uri of the combined image
                imageObject.lib      = combinedImageObject.lib
                imageObject.mtype    = combinedImageObject.type
                imageObject.mlib     = combinedImageObject.lib

                # and store it in the data structure
                data[imageShortUri]  = imageObject.flatten()  # this information takes precedence over existing

            return
    def generateResourceInfoCode(self, settings, libs, format=False):
        """Pre-calculate image information (e.g. sizes)"""
        data    = {}
        resdata = data
        imgpatt  = re.compile(r'\.(png|jpeg|jpg|gif)$', re.I)
        skippatt = re.compile(r'\.(meta|py)$', re.I)

        self._console.info("Analysing assets...")
        self._console.indent()

        self._imageInfo      = ImageInfo(self._console, self._cache)

        # some helper functions

        def replaceWithNamespace(imguri, liburi, libns):
            pre,libsfx,imgsfx = Path.getCommonPrefix(liburi, imguri)
            if imgsfx[0] == os.sep: imgsfx = imgsfx[1:]  # strip leading '/'
            imgshorturi = os.path.join("${%s}" % libns, imgsfx)
            return imgshorturi

        def extractAssetPart(libresuri, imguri):
            pre,libsfx,imgsfx = Path.getCommonPrefix(libresuri, imguri) # split libresuri from imguri
            if imgsfx[0] == os.sep: imgsfx = imgsfx[1:]  # strip leading '/'
            return imgsfx                # use the bare img suffix as its asset Id

        ##
        # calculate the uri of the clipped image, by taking the uri of the combined image,
        # "substracting" its asset id (the right end), taking what remains (the left
        # part), extracting the asset id of the clipped image, and pre-fixing it with the
        # left part of the combined image uri.
        # imageUri = (combinedUri - combinedAssetId) + imageAssetId
        #
        # @param uriFromMetafile |String| the path of the clipped image from when the meta file was generated,
        #                                 like: "./source/resource/qx/decoration/Modern/..."
        # @param trueCombinedUri |String| the uri of the combined image, as returned from
        #                                 the library scan and adapted for the current
        #                                 application, like: 
        #                                 "../../framework/source/resource/qx/decoration/Modern/panel-combined.png"
        # @param combinedUriFromMetafile |String| the path of the combined image, as
        #                                         recorded in the .meta file

        def normalizeImgUri(uriFromMetafile, trueCombinedUri, combinedUriFromMetafile):
            # normalize paths (esp. "./x" -> "x")
            (uriFromMetafile, trueCombinedUri, combinedUriFromMetafile) = map(os.path.normpath,
                                                    (uriFromMetafile, trueCombinedUri, combinedUriFromMetafile))
            # get the "wrong" left part of the combined image, as used in the .meta file (in mappedUriPrefix)
            trueUriPrefix, mappedUriPrefix, _ = Path.getCommonSuffix(trueCombinedUri, combinedUriFromMetafile)
            # ...and strip it from clipped image, to get a correct image id (in uriSuffix)
            _, _, uriSuffix = Path.getCommonPrefix(mappedUriPrefix, uriFromMetafile)
            # ...then compose the correct prefix with the correct suffix
            normalUri = os.path.normpath(os.path.join(trueUriPrefix, uriSuffix))
            return normalUri

        ##
        # - reads through the entries of a .meta file, which is the contents of a combined image
        # - for each contained image:
        #   - computes the image id ("short uri")
        #   - collects the list of interesting values (width, height, ..., combined image, ...)
        #   - and adds these as key:value to the general data map of images
        #
        # @param data |{imageId:[width, height, ...]}|  general map for qx.$$resource in loader
        # @param meta_fname |String| file path of the .meta file
        # @param combinedImageUri |String| uri of the combined image
        # @param combinedImageShortUri |String| short uri (image/asset id) of the combined image
        #                              these are necessary to compute the image id's of the contained imgs
        # @param combinedImageObject |ImgInfoFmt| an ImgInfoFmt wrapper object for the combined image
        #                             (interesting for the lib and type info)

        def processCombinedImg(data, meta_fname, combinedImageUri, combinedImageShortUri, combinedImageObject):
            # make sure lib and type info for the combined image are present
            assert combinedImageObject.lib, combinedImageObject.type

            # see if we have cached the contents (json) of this .meta file
            cacheId = "imgcomb-%s" % meta_fname
            imgDict = self._cache.read(cacheId, meta_fname)
            if imgDict == None:
                mfile = open(meta_fname)
                imgDict = simplejson.loads(mfile.read())
                mfile.close()
                self._cache.write(cacheId, imgDict)

            # now loop through the dict structure from the .meta file
            for imagePath, imageSpec_ in imgDict.items():
                # sort of like this: imagePath : [width, height, type, combinedUri, off-x, off-y]

                imageObject = ImgInfoFmt(imageSpec_) # turn this into an ImgInfoFmt object, to abstract from representation in .meta file and loader script

                # have to normalize the uri's from the meta file
                #imageUri = normalizeImgUri(imagePath, combinedImageUri, imageObject.mappedId)
                imageUri = imagePath

                ## replace lib uri with lib namespace in imageUri
                imageShortUri = extractAssetPart(librespath, imageUri)
                imageShortUri = Path.posifyPath(imageShortUri)

                # now put all elements of the image object together
                imageObject.mappedId = combinedImageShortUri        # correct the mapped uri of the combined image
                imageObject.lib      = combinedImageObject.lib
                imageObject.mtype    = combinedImageObject.type
                imageObject.mlib     = combinedImageObject.lib

                # and store it in the data structure
                data[imageShortUri]  = imageObject.flatten()  # this information takes precedence over existing

            return


        # -- main --------------------------------------------------------------

        resourceFilter= self._resourceHandler.getResourceFilterByAssets(self._classList)

        for lib in libs:
            #libresuri = self._computeResourceUri(lib, "", rType='resource', appRoot=self.approot)
            librespath = os.path.normpath(os.path.join(lib['path'], lib['resource']))
            resourceList = self._resourceHandler.findAllResources([lib], resourceFilter)
            # resourceList = [[file1,uri1],[file2,uri2],...]
            for resource in resourceList:
                ##assetId = replaceWithNamespace(imguri, libresuri, lib['namespace'])
                #assetId = extractAssetPart(libresuri, resource[1])
                assetId = extractAssetPart(librespath,resource)
                assetId = Path.posifyPath(assetId)

                if imgpatt.search(resource): # handle images
                    imgpath= resource
                    #imguri = resource[1]
                    imguri = resource
                    imageInfo = self._imageInfo.getImageInfo(imgpath, assetId)

                    # use an ImgInfoFmt object, to abstract from flat format
                    imgfmt = ImgInfoFmt()
                    imgfmt.lib = lib['namespace']
                    if not 'type' in imageInfo:
                        raise RuntimeError, "Unable to get image info from file: %s" % imgpath
                    imgfmt.type = imageInfo['type']

                    # check for a combined image and process the contained images
                    meta_fname = os.path.splitext(imgpath)[0]+'.meta'
                    if os.path.exists(meta_fname):  # add included imgs
                        processCombinedImg(data, meta_fname, imguri, assetId, imgfmt)

                    # add this image directly
                    # imageInfo = {width, height, filetype}
                    if not 'width' in imageInfo or not 'height' in imageInfo:
                        raise RuntimeError, "Unable to get image info from file: %s" % imgpath
                    imgfmt.width, imgfmt.height, imgfmt.type = (
                        imageInfo['width'], imageInfo['height'], imageInfo['type'])
                    # check if img is already registered as part of a combined image
                    if assetId in data:
                        x = ImgInfoFmt()
                        x.fromFlat(data[assetId])
                        if x.mappedId:
                            continue  # don't overwrite the combined entry
                    data[assetId] = imgfmt.flatten()

                elif skippatt.search(resource[0]):
                    continue

                else:  # handle other resources
                    resdata[assetId] = lib['namespace']


        # wpbasti: Image data is not part relevant yet.

        self._console.outdent()

        return resdata