Recent

Author Topic: DIBS for the mac?  (Read 5720 times)

wotanica

  • Guest
DIBS for the mac?
« on: September 11, 2010, 04:36:12 am »
I realize that DIB's is a purely microsoft invention (although the concept of device independence is probably universal), but I am in the process of porting over some graphics code and I could use a hand.

Basically what i need is:
1. Being able to allocate an offscreen raster or "handle" for my own buffer.
2. Being able to read/write to above raster's memory directly
3. Being able to blit/copy/draw said buffer onto a form handle or control surface directly ("blitting")

My library is fairly straightforward. I have isolated as much as possible in a "TSLCustomRaster" class, and then simply inherited from this a DIB implementation (on windows) and also a "raw" implementation that just uses AllocMem() for it's buffer. So I can at least draw into a memory buffer. The idea is to make it as portable as possible (with freepascal in mind).

Please, any pointers to what i must read, api calls etc.. is very welcome.
ALso for linux if you have it. It would be very cool to have my library running on both linux, mac and windows.
I also have created codecs for gif, jpg (libjpg linking), bmp, ico and png (not ready yet). It's one unit and well under 10k lines of code.

It implements most primitives such as plot, line, circle, rect, polygon (each primitive can be drawn as wire, filled and anti-alias). Pure pascal, portable and fast. Nearly no assembler, and compiler switches to disable platform dependent features. This project is a "basis" that more advanced libraries can make use of.

All i need is the API calls that makes it talk with the OS to get the buffer....
« Last Edit: September 11, 2010, 04:41:40 am by wotanica »

wotanica

  • Guest
Re: DIBS for the mac?
« Reply #1 on: September 11, 2010, 05:21:37 am »
Sneaking around the Lazarus code, i had a look in the macosall unit, and found an API function called CGImageCreate(). The syntax for it reminds me of CreateDibSection() on windows.
I am unsure how to use it though. I suspect i must create a "dataprovider" that points a memory buffer (?)

Hope someone can help me out with this, I have a lot of code that depends on my graphics library - and getting the blitter working is make or break for my project.

Googlig I found the following CPP code:

provider = CGDataProviderCreateDirectAccess((void*)dispBitsIndex
            + pitch*affectedT
            + affectedL*(depth==32 ? 4 : 2),  
            pitch * (affectedB-affectedT)-affectedL*(depth==32 ? 4 : 2),
            &gProviderCallbacks);
   image = CGImageCreate( affectedR-affectedL, affectedB-affectedT, depth==32 ? 8 : 5 /* bitsPerComponent */,
            depth /* bitsPerPixel */,
            pitch, colorspace, kCGImageAlphaNoneSkipFirst, provider, NULL, 0, kCGRenderingIntentDefault);

   clip = CGRectMake(affectedL,height-affectedB, affectedR-affectedL, affectedB-affectedT);

(..)

   /* Draw the image to the Core Graphics context */
   CGContextDrawImage(targetWindowBlock->context, clip, image);
   
(..)
   
   CGImageRelease(image);
   CGDataProviderRelease(provider);
« Last Edit: September 11, 2010, 05:48:58 am by wotanica »

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2269
    • havefunsoft.com
Re: DIBS for the mac?
« Reply #2 on: September 11, 2010, 06:02:43 am »
If you're using LCL, you might want to use Platform independent code (see fading example):

http://wiki.freepascal.org/Developing_with_Graphics#Working_with_TBitmap

Otherwise:
Being able to allocate an offscreen raster or "handle" for my own buffer.
you should use CGBitmapContextCreate or CGBitmapContextCreateWithData

2. Being able to read/write to above raster's memory directly
The returned CGContextRef can be used for drawing via CGContext functions. You can also write or read the data buffer provided on the bitmap creation .

3. Being able to blit/copy/draw said buffer onto a form handle or control surface directly
This is possible, using CGBitmapContextCreateImage. However, the created image is actually a lazy copy of the current bitmap state. Further changes on the bitmap, won't cause the created image to change, you must to create another image with the same function.

After the image has been created you can draw it on another bitmap and/or control's surface  using CGContextDrawImage

Please read Quartz 2D Programming Guide, you might want to learn about Bitmap Images and probably Layers

DataProviders, you've mentioned before, are used for loading images from files, custom streams or any kind of data storage.
« Last Edit: September 11, 2010, 06:20:37 am by skalogryz »
Patron Cocoa Widgetset development https://www.patreon.com/skalogryz

wotanica

  • Guest
Re: DIBS for the mac?
« Reply #3 on: September 11, 2010, 06:26:04 am »
thanx!
Having looked over it, it seems to be the same as on windows.
Im not looking for "components" or being able to have an image in a picture box so to speak, but being able to quickly dump a raster onto a form, or indeed - copy it in memory to another raster by accessing the bytebuffers directly.

So yes, having to redraw per change is just what i wanted.
Unless i select the bitmap into a viewport(?) the changes will not be visible unless i update the graphics component.

The whole idea is that copying between bitmaps directly, scaling, clipping etc. can be done more efficiently on-the-fly, rather than depending on the OS for everything. And that makes it platform independent as long as the derived class implements the "basics" for that platform (e.g dibs on windows, xyz on mac, xyz on linux).

Will read up on this, thanx!
« Last Edit: September 11, 2010, 06:27:55 am by wotanica »

wotanica

  • Guest
Re: DIBS for the mac?
« Reply #4 on: September 11, 2010, 03:54:58 pm »
Just wanted to comment further, I was quite tired when i replied above.

For Delphi there are a bunch of graphics libraries. Most of them exist because the standard Delphi TBitmap has some serious limitations on Windows. Windows allocates Bitmaps and links them to the application instance. I dont remember all the details on this, but it caused a lot of problems on XP and a phenomena where you would get "out of memory" if you allocated and released to many bitmaps in sequence.

I once did a test on XP that looked something like this:

Code: [Select]
for x:=1 to 10000 do
Begin
  FBitmap:=TBitmap.Create;
  try
    FBitmap.pixelformat:=pf24Bit;
    FBitmap.Width:=400;
    FBitmap.Height:=400;
    /* draw stuff */
    FBitmap.Dormant;
    BitBlt( ..) //to mainform
  finally
    FreeAndNIL(FBitmap);
  end;
end;

It resulted in an "out of memory" exception, because somehow Windows did not release the memory until the application instance was terminated. Sometimes it worked for a while but it always crashed. I discovered this when i was coding a simple thumbnail browser that cashed 64 bitmaps in memory for drawing. It would work for a while, but after scrolling around it would crash.

Then I coded my own DIBS class that just held the pixels in a memory buffer with a device context -- and no problems at all.

I then decided to code a "mini" library that implemented DIB bitmaps, and also a Canvas implementation that would write directly to the DIB's memory buffer. This was further developed into different types. When coding win32 services that process large TIFF or JPG files - I dont even need a device context. I could simply load in the pictures in a memory buffer and scale them down using my own code. This was much faster than relying on the VCL.

Now I want to extend this library to also work on the MAC (and linux), so i need the code for creating offscreen bitmaps on the mac (for blitting onto control surfaces, forms etc.). It should also be able to use TCanvas (e.g "FCanvas:=TCanvas.Create(MyRaster.DC);". 99% of the library is pure pascal, making it ultra portable just like the LCL.

Thans for pointing me in the right direction :)
« Last Edit: September 11, 2010, 03:56:35 pm by wotanica »