azrafe7 / hxPixels

An hxperimental (cross-target/cross-lib) Pixels abstract, in Haxe 3.1+
MIT License
20 stars 1 forks source link

Virtual graphics support? #1

Open Justinfront opened 9 years ago

Justinfront commented 9 years ago

Azrafe7 I was thinking that it would be ideal to have hxPixel abstraction above: https://github.com/HaxeFoundation/format/tree/master/format/jpg https://github.com/HaxeFoundation/format/tree/master/format/gif https://github.com/HaxeFoundation/format/tree/master/format/png https://github.com/HaxeFoundation/format/tree/master/format/swf https://github.com/HaxeFoundation/format/tree/master/format/bmp I am thinking that a complementary library hxVector might be ideal and have been considering aspects like virtual hittest and generation of pixels.. slow generation but reasonable fast hittesting.
The idea is that while we can target a graphic platform sometimes it's useful to have a target that does not have a visual output but is just a processing target, so you could from bitmaps create meshes on a server and haxeRemote them to a front end for instance. So adding one or more virtual targets would be quite powerful? Best Justin

azrafe7 commented 9 years ago

Taking a look at how format works under the hood, it should be quite easy to integrate/interface it with hxPixels. Basically the various submodules already have the needed methods to convert to/from Bytes (in Tools.hx). So should be a matter of assigning/blitting those bytes to pixels.bytes and setting the correct width/height/PixelFormat... going to test if this is as easy as it seems from this quick glance soon.

Anyway... do you intend this to work read-only, or there's a need to write it back too (rephrased: only fromPNGData(data:format.png.Data):Pixels, or toPNGData() too)?

azrafe7 commented 9 years ago

Drafting out some thoughts about how we can tackle this:

azrafe7 commented 9 years ago

Sounds good?

Justinfront commented 9 years ago

sounds good but I don't follow it all seems it could be very useful. One aspect not covered is what might be ideal for pixel remoting or maybe just passing png between is better due to sizes.

azrafe7 commented 9 years ago

Ok, I've played with this a bit. I've put the results in the lib-format branch of hxPixels (https://github.com/azrafe7/hxPixels/tree/de3cb0131959435ba29f46229bd3070e0a6b44a8).

Currently converts from png, bmp and gif formats to a Pixels abstract. Bmp needs a patch to the format lib to work correctly, as it doesn't account for some things described in https://msdn.microsoft.com/en-us/library/windows/desktop/dd318229(v=vs.85).aspx (I'll send a PR there when/if I manage to write one, but it's not really necessary since bmp files tend to be large and not much useful when compared to pngs).

You can test it by compiling format_build.hxml. It will process all the resources and write the modified images as pngs.

Think I'll add a add a pixel format converter for hxPixels soon to complete the scene.

azrafe7 commented 9 years ago

Also... I'm curious to know if it works with both type of byte endian-ness (I'm on win), so if you can test it on mac and report back I'd be glad (even better if you can test with additional image resources/files you have lying around on your mac).

Justinfront commented 9 years ago

That looks really cool all format seem to work accept bmp that has vertical banding, I played with code but did not work out how to change it. Well I worked out how to manipulate it to some degree. Do you know exactly what the missing row data is that makes it have vertical bars is it using dithering to reduce the number of rows needed? I did not yet test in on other images.

azrafe7 commented 9 years ago

Replace the read() function in format.bmp.Reader with:

    public function read() : format.bmp.Data {
        // Read Header
        for (b in [66, 77])
        {
          if (input.readByte() != b) throw "Invalid header";
        }

        var fileSize = readInt();
        readInt(        );                      // Reserved
        var offset = readInt();

        // Read InfoHeader
        var infoHeaderSize = readInt();         // InfoHeader size
        var width = readInt();                  // Image width
        var height = readInt();                 // Image height
        var numPlanes = input.readInt16();      // Number of planes
        var bits = input.readInt16();           // Bits per pixel (24bit BGR)
        var compression = readInt();            // Compression type (no compression)
        var dataLength = readInt();             // Image data size
        readInt();                              // Horizontal resolution
        readInt();                              // Vertical resolution
        readInt();                              // Colors used (0 when uncompressed)
        readInt();                              // Important colors (0 when uncompressed)

        // If there's no compression, the dataLength may be 0
        if( compression == 0 && dataLength == 0 ) dataLength = fileSize - offset;

        if (bits != 24) throw '${bits}bpp bitmaps not implemented.';

        var p = haxe.io.Bytes.alloc( dataLength );

        // Read Raster Data
        // https://msdn.microsoft.com/en-us/library/windows/desktop/dd318229(v=vs.85).aspx
        var paddedStride = ((((width * bits) + 31) & ~31) >> 3);
        var stride = width * 3;
        var paddedRow = haxe.io.Bytes.alloc( paddedStride );
        var yDir = -1;
        var dstPos = dataLength + yDir * stride; 
        var pos = 0;
        if( height < 0 ) { // bitmap is stored top to bottom
            height = -height;
            yDir = 1;
            dstPos = 0;
        }

        while (pos < dataLength) {
            input.readFullBytes(paddedRow, 0, paddedStride);
            p.blit(dstPos, paddedRow, 0, stride);
            pos += paddedStride;
            dstPos += yDir * stride;
        }
        return {
            header: {
                width: width,
                height: height
            },
            pixels: p
        }
    }

Although that should work correctly, there are a few things that should probably be fixed before making it into a PR: