Skip to main content
Known Participant
February 9, 2011
Question

Code works on MacOs but doesn't on Windows

  • February 9, 2011
  • 12 replies
  • 3565 views

Hi there,

I have another question.

This code exports the artboards in jpg with the a resolution of 300dpi. Everything works  on MacOs 10.6.6 and AI CS5.

I manage to export the jpg on Win 7 x64 and AI CS5 but can't manage to set any of the parameters in 1885434477 ('parm').

Is there anything special to do on Windows?

Thank you very much for your help.

typedef struct

{

    long quality;

    long kind;

    long scans;

    long antialias;

     AIFixed resolution;

    long colorModel;

    long alwaysTrue;

    long unused[18];

} jpegExportParametersCS5;

jpegExportParametersCS5 jpegExportParameters = {6,1,1,1,65535*300,3,1,1};

error = sAIActionManager->AIActionSetRawDataBytes(valueParameterBlock, 1885434477, (ASUInt32) sizeof(jpegExportParameters), (const char*) &jpegExportParameters);

error = sAIActionManager->PlayActionEvent("adobe_exportDocument", kDialogOff, valueParameterBlock);


This topic has been closed for replies.

12 replies

Known Participant
February 14, 2011

Okay,

Forgot the last message.

It works very well on Mac as well.

I got fooled by the "Preview" mac application that obviously read the dpi correctly.

After opening the same jpg file in Photoshop I could see that the dpi was at 300.

Thanks again.

I think we can put that one to rest!

Andrew I own you a beer (or two)!

TheDollarBill
Known Participant
August 2, 2012

Okay, so now that we are on CS6, using this:

typedef struct JPGoptionsModified

{

     long quality;

     long kind;

     long scans;

     AIBoolean antiAlias;

     AIFixed dpi;

     long colorModel;

     int makeImageMap;

     int mapType;

     ASUnicode mapName[33];

     AIBoolean embedded;

}JPGoptions;

produces the desired jpeg and ai files but also produces and extraneous .html file.  I have gotten this extraneous html file before when transitioning from one version to another and found it was due to using an incorrect parameter block, but I can't figure out how to make it right for cs6.  Everything seems to be the same except that "makeImageMap" and "mapType" seem to be switched. 

ANY ideas??

Here's a cs5 action export:

/value < 100

                                        0a0000000200000003000000030000000000f401020000000100000000000000

                                        55006e007400690074006c00650064002d003100000000000000000000000000

                                        0000000000000000000000000000000000000000000000000000000000000000

                                        00000100

                              >

                              /size 100

And here's a cs6 action export:

/value < 100

                                        0a0000000300000003000000030000000000f401020000000000000001000000

                                        69006d006100670065006d006100700000003100000000000000000000000000

                                        0000000000000000000000000000000000000000000000000000000000000000

                                        00000100

                              >

                              /size 100

Known Participant
February 14, 2011

I tried the same structure on the mac.

the resolution of the generated jpg is 72 dpi but the file is bigger (X and Y)

I will keep my original structure on the mac and try to investigate further more then send you my findings.

Thanks again.

Known Participant
February 14, 2011

I was also trying to make the struct 104 on the pc.

But I was shift bytes at the begining of the struct and it was making AI crash.

Thanks again.

Known Participant
February 14, 2011

Andrew,

Your the man!

That works!

Can you enlight me and explain where the problem was?

Should I also use the same struct on the mac?

Thanks again for your time.

Benoit.

A. Patterson
Inspiring
February 14, 2011
Can you enlight me and explain where the problem was?

Should I also use the same struct on the mac?

The problem was just the chars weren't chars. They were ASUnicode. They probaby were chars back in CS2 or CS3, but somewhere along the way they became unicode. I would try it on the Mac too, but check the sizeof() -- I suspect it will work out to be 100 as we'd expect.

And I'm glad to hear its working!  Hopefully it will be fine on the Mac and this mystery will be solved. Frankly, this struct should be in an action header in the Actions folder of the SDK. I'm not sure why its not. Expecting us to reverse engineer action parameter's raw binary structs is asking a little much

Known Participant
February 14, 2011

typedef struct

{

     long quality; // 0-10, sucky to maximum

     long kind; // 0 = baseline, 1 = optimized, 2 = progressive

     long scans; // 1-3, actually means 3, 4 or 5

     AIBoolean antiAlias; // your choice

     AIFixed dpi; // short << 16

     long colorModel; // 1 = rgb, 2 = cmyk, 3 = gray

     int makeImageMap; // will always be true no matter what you set

     int mapType; // clientside = 0, serverside = 1

     char mapName[33];

     AIBoolean embedded;

} jpegExportParametersCS5;

on pc sizeof(jpegExportParametersCS5) = 72

on mac sizeof(jpegExportParametersCS5) = 68

As you said it looks like there's a 4 byte difference.

....

The above struct doesn't work on mac. I still use the following one that returms a size of 100 and that works.

typedef struct

{

    long quality;

    long kind;

    long scans;

    long antialias;

AIFixed resolution;

    long colorModel;

    long alwaysTrue;

    long unused[18];

} jpegExportParametersCS5;

A. Patterson
Inspiring
February 14, 2011

Well, that struct is size 100, naturally, since you've got 7 longs and one array of 18 longs; that meaks 25 longs and since they're all 4 bytes, that's 100 bytes.

Try this:

typedef struct JPGoptionsModified

{

     long quality;

     long kind;

     long scans;

     AIBoolean antiAlias;

     AIFixed dpi;

     long colorModel;

     int makeImageMap;

     int mapType;

     ASUnicode mapName[33];

     AIBoolean embedded;

}JPGoptions;

A. Patterson
Inspiring
February 14, 2011

I just checked, and that struct is 104 bytes on Windows. I suspect its 100 on Mac, but I have no way to check right this minute.

Known Participant
February 14, 2011

Would these 2 extra bytes be the reason why the size on the MAc is 100 and is 104 on the PC?

In the getting started guide there's the following concerning the configuration of the dev environment on Windows:


"Set Struct Member Alignment to 4 Bytes (/Zp4)."


would it have anything to do with my problem here?

I'm also using Visual Studio 10. Is it bad????


Andrew thank you very much for your time.

Best regards,

A. Patterson
Inspiring
February 14, 2011

The four-byte alignment does support my (admittedly shot-in-the-dark) theory. I'm afraid I know just enough about byte alignment to be a menace

First, I don't think VS2010 is the problem. That really only becomes trouble if AI is passing you objects and you're deleting them, but they have a mostly C-style interface & Free*() methods for pretty much anything that looks like a handle. So I think you're safe there.

I suspect its far more likely a problem with the char[33] member. It looks to me like that should be ASUnicode[33]. It could well be that working on the Mac is just a fluke.

Out of curiosity, I know you're using sizeof() when you make the call to AIActionSetRawDataBytes(), but what does that actually return on each platform? I'm guessing you should see 104 & 100 as your results if the structs are setup right.

Known Participant
February 14, 2011

Hi Andrew,

I did use you technic to get the right parameter.

I recorded the export on both machines with the same parameters:

Quality 6

res 300dpi

Color Model CMYK

Methoe Baseline Optimized

Anti-Aliasing none

image map server side on the Mac

image map client on the PC (Couldn't change it)

here's the value of param on the PC:

/key 1885434477

/showInPalette 0

/type (raw)

/value < 104

0600000001000000030000000100000000002c01020000000100000000000000

520061006300650054007200610063006b000000000000000000000000000000

0000000000000000000000000000000000000000000000000000000000000000

0000000001000000

>

/size 104

here's the value of param on the Mac:
/key 1885434477
/showInPalette 0
/type (raw)
/value < 100
0600000001000000020000000100000000002c01020000000100000001000000
520061006300650054007200610063006b000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00000100
>
/size 100
A. Patterson
Inspiring
February 14, 2011

Okay, assuming the struct looks like this (in order):

long quality; // 0-10, sucky to maximum [4 bytes]

long kind; // 0 = baseline, 1 = optimized, 2 = progressive [4 bytes]
long scans; // 1-3, actually means 3, 4 or 5 [4 bytes]
AIBoolean antiAlias; // your choice [4 bytes on Windows, 1 byte on Mac]
AIFixed dpi; // short << 16 [long on both platforms, 4 bytes]
long colorModel; // 1 = rgb, 2 = cmyk, 3 = gray [4 bytes]
int makeImageMap; // will always be true no matter what you set [4 bytes]
int mapType; // clientside = 0, serverside = 1 [4 bytes]
char mapName[33]; [see below]
AIBoolean embedded; [4 bytes on Windows, 1 byte on Mac]

------------------------------------------------

0600000001000000030000000100000000002c01020000000100000000000000

520061006300650054007200610063006b000000000000000000000000000000

0000000000000000000000000000000000000000000000000000000000000000

0000000001000000

Becomes:

06 00 00 00 - quality [6]
01 00 00 00 - kind [optimized]
03 00 00 00 - scans [5]
01 00 00 00 - antiAlias [true]
00 00 2c 01 - dpi [300]
02 00 00 00 - colorModel [CMYK]
01 00 00 00 - makeImageMap [true]
00 00 00 00 - mapType [clientside]

52 00 61 00 - R a
63 00 65 00 - c e
54 00 72 00 - T r
61 00 63 00 - a c
6b 00 00 00 - k

00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00

00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00

00 00 00 00
00 00 00 00 - this makes 68 bytes, which is 34 unicode characters, not 33 as one might expect

01 00 00 00 - embedded [true]

And

0600000001000000020000000100000000002c01020000000100000001000000

520061006300650054007200610063006b000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00000100

Becomes:

06 00 00 00 - quality [6]
01 00 00 00 - kind [optimized]
02 00 00 00 - scans [4]
01 00 00 00 - anitAlias [true]
00 00 2c 01 - dpi [300]
02 00 00 00 - colorModel [CMYK]
01 00 00 00 - makeImageMap [true]
01 00 00 00 - mapType [serverside]

52 00 61 00 - R a
63 00 65 00 - c e
54 00 72 00 - T r
61 00 63 00 - a c
6b 00 00 00 - k

00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00

00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00

00 00 00 00
00 00 01 00 - oddity the '01' is probably the embedded, but the byte count is off

A few notes:

Given the layout of the string for mapName, I suspect its actually 33 unicode characters, not 33 char. Though there seems to be a difference between the Mac & Windows on the size of this field; it may be byte alignment, something I'm grossly uninformed on.

Next, while some of the parameters are different (I'm not sure why, perhaps Benoit didn't quite make both actions exactly the same) they're pretty close. The major difference seems to be at the end. There are an extra four zeroes, but I think that actually makes two bytes. It could just be some kind of byte alignment or padding though.

The fact that the Mac ends with 01 00 instead of 01 00 00 00 lends credence to the idea that there's a typedef at work here. I think that might be AIBoolean rearing its head and the Mac is aligning to four-bytes? I'm not sure. That would mean the first boolean (antiAlias) is actually only the first byte in the Mac breakdown and the next three bytes are filler. If its not that though, I'm at a loss to explain why 01 00 makes sense at the end, unless I've broken down the bytes very badly.

Known Participant
February 14, 2011

Hi guys,

Thanks again for lookng into this.

Here's the exact code:

typedef struct

{

     long quality; // 0-10, sucky to maximum

     long kind; // 0 = baseline, 1 = optimized, 2 = progressive

     long scans; // 1-3, actually means 3, 4 or 5

     AIBoolean antiAlias; // your choice

     AIFixed dpi; // short << 16

     long colorModel; // 1 = rgb, 2 = cmyk, 3 = gray

     int makeImageMap; // will always be true no matter what you set

     int mapType; // clientside = 0, serverside = 1

     char mapName[33];

     AIBoolean embedded;

} jpegExportParametersCS5;

AIActionParamValueRef valueParameterBlock = nil;

error = sAIActionManager->AINewActionParamValue(&valueParameterBlock);

if (valueParameterBlock)

{

jpegExportParametersCS5 jpegExportParameters = {

6, // 0-10, sucky to maximum

1, // 0 = baseline, 1 = optimized, 2 = progressive

1, // 1-3, actually means 3, 4 or 5

true, // your choice

300 << 16, // short << 16

1, // 1 = rgb, 2 = cmyk, 3 = gray

1, // will always be true no matter what you set

1, // clientside = 0, serverside = 1

"test",

false

};

error = sAIActionManager->AIActionSetString(valueParameterBlock, kAIExportDocumentNameKey,"C:\\temp\\test.jpg");

error = sAIActionManager->AIActionSetString(valueParameterBlock, kAIExportDocumentFormatKey, "JPEG file format");

error = sAIActionManager->AIActionSetBoolean(valueParameterBlock, kAIExportDocumentSaveMultipleArtboardsKey, true);

error = sAIActionManager->AIActionSetBoolean(valueParameterBlock, kAIExportDocumentSaveAllKey, true);

error = sAIActionManager->AIActionSetString(valueParameterBlock, kAIExportDocumentExtensionKey, "jpg");

error = sAIActionManager->AIActionSetRawDataBytes(valueParameterBlock, 'parm', (ASUInt32) sizeof(jpegExportParametersCS5), (const char*) &jpegExportParameters);

error = sAIActionManager->PlayActionEvent("adobe_exportDocument", kDialogOff, valueParameterBlock);

error = sAIActionManager->AIDeleteActionParamValue(valueParameterBlock);

}

February 11, 2011

I think the problem is that while you have the length of the struct right, you can't just assume that the last 18 longs are unused. Here is the struct as we figured it out in CS4

typedef struct JPGoptions

{

     long quality; // 0-10, sucky to maximum

     long kind; // 0 = baseline, 1 = optimized, 2 = progressive

     long scans; // 1-3, actually means 3, 4 or 5

     AIBoolean antiAlias; // your choice

     AIFixed dpi; // short << 16

     long colorModel; // 1 = rgb, 2 = cmyk, 3 = gray

     int makeImageMap; // will always be true no matter what you set

     int mapType; // clientside = 0, serverside = 1

     char mapName[33];

     AIBoolean embedded;

}JPGoptions;

I notice that you have alwaysTrue where I have makeImageMap, which is the case (it will always be true). It's because of this that the image map name should be set. Just use "Unused ImageMap" or something like that. Windows should be happy with that.

So much fun when working with undocumented structs :-)

Brendon

February 11, 2011

I also just noticed that the struct you are using is different that the one we use. Where did you get this struct?

Brendon

Known Participant
February 11, 2011

I got that structure from the forum.

I also tried this which isn't working either:

struct AIImageOptJPEGParams{
    ai::int32 quality;
    AIImageOptJPEGKind kind;
    ai::int32 scans;
    AIFloat blurAmount;

    AIFloat resolution;

    AIBool8 outAlpha;

    ai::int32 outWidth;

    ai::int32 outHeight;

};

I notice that If I record my export manually from the Mac and from the PC.

I end up with the param 'parm' of a size of 100 bytes on the Mac and 104 bytes on the PC.

I also looked at the memory address to make sure what's stored in my 'parm' variable has the same value as the one in the my recorded action.

Benoit.

A. Patterson
Inspiring
February 11, 2011
I notice that If I record my export manually from the Mac and from the PC.

I end up with the param 'parm' of a size of 100 bytes on the Mac and 104 bytes on the PC.

Just wanted to chime in here and point out what is probably obvious -- the sizes are probably different since there are typedefs involved. I know that AIBoolean is very different between Mac & Windows (which is why I believe they use AIBool8 now). Even if you had the right structure in spirit, not having the right typedef for some of them could cause some odd structure alignment issues.

And yes, undocumented structs are a lot of fun