hi all,
I am using gm magick core c api for PNG converting in nginx module.
The pseudo code as following:
1. get post body from http request;
2. call BlobToImage() to convert the posted data to a image for image handling such as resize/crop etc.;
3. call ImageToBlob() to format the handled image to blob and return to caller.
As for common image types other than PNG, this works fine.
When I want to convert a PNG file to the smallest filesize, i can not find the right way to set the effective params for ImageToBlob() , it tskes no effect!
But i find using cmd line works! like that: gm convert input.png -resize120x120 -depth 8 -colors 256 -quality 75 output.png.
With cmd line, parameter depth/colors/quality can works well.
depth can be set 1/2/4/8/16/24/32.
colors can be set 256.
As I try many ways to set those params in ImageToBlob(ImageInfo, Image), like depth in ImageInfo, depth/colors in Image, all are useless, filesize is not decreased much.
especially, depth set lower than 8 will be reset to 8 when call ImageToBlob.
I have read source code of GM 1.3.17, hope to take advantage of gm's implementation, but failed
Anyone can help? thanks a lot.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Your command line is requesting several image processing operations (e.g. resize). Between reading and writing the image, you would need to apply several image processing operations using the C API. Most of the code which does this for the command line is in MogrifyImage() in magick/command.c.
The PNG format itself does not support less "depth" than 8.
Bob
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The PNG format supports depths less than 8 for grayscale and indexed images, but I'm not sure that the GM png encoder does.. By the way, -quality 70 will probably give you better compression than 75 for less-than-257-color images. If you are really concerned about PNG filesize, I recommend postprocessing them with pngcrush after you've written them with GM.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
thanks to bfriesenand glennrp. I had read gm/coders/png.c, and found depth for png will be set to 8 if given less than 8. But how does gm make it with option -depth and -colors?
During ResizeImage(), it does not require any depth and colors paramters.
As for this:gm convert input.png -depth 8 -colors 256 -quality 75 output.png.
this cmd also takes effect and decrease filesize much.
So i am curious to find out how do GM to apply these options(depth and colors), as both of you say that PNG format does not support depth less than 8.
looking forwards to your reply.
riccy
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Glenn has already corrected me in that PNG can support fewer bits/sample for gray and colormapped images, however, I suspect that PNG still uses 8-bits per color sample for its color pallet.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Be careful about using SetImageDepth(). This function actually modifies the image pixels so that each quantum (color-component value) is cleanly representable in the specified number of bits. It does this by integer dividing and then multiplying. This will definitely make the output file smaller but also causes a loss of color quality since each color quantum can have no more than 16 values rather than 256. Using the image->depth=8 approach won't result in worse color quality.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
hi bfriesen,
I read code of MogrifyImage() and try to use QuantizeImage() with the given QuantizeInfo structure, this also works.
No much difference between setting depth to 4 and setting colors to 256.
The following is my code refer to the code of MogrifyImage() in magick/command.c:
#define IMAGE_DEFAULT_DEPTH 24
#define IMAGE_DEFAULT_COLORS 65535
if (IMAGE_DEFAULT_DEPTH != param.depth) {
SetImageDepth(imgs.processed_image, param.depth);
}
if (IMAGE_DEFAULT_COLORS != param.colors) {
QuantizeInfo quantize_info;
GetQuantizeInfo(&quantize_info);
quantize_info.number_colors = param.colors;
quantize_info.tree_depth = 0;
quantize_info.dither = MagickTrue;
if (IsGrayColorspace(quantize_info.colorspace)) {
if (quantize_info.number_colors != 0)
(void) QuantizeImage(&quantize_info, imgs.processed_image);
else
(void) TransformColorspace(imgs.processed_image, quantize_info.colorspace);
} else {
if (quantize_info.number_colors != 0) {
if ((imgs.processed_image->storage_class == DirectClass) ||
(imgs.processed_image->colors > quantize_info.number_colors)) {
(void) QuantizeImage(&quantize_info, imgs.processed_image);
} else {
CompressImageColormap(imgs.processed_image);
}
}
}
}
This code is supposed to take effect when given depth or colors parameters.
thanks a lot.
riccy
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
hi all,
I am using gm magick core c api for PNG converting in nginx module.
The pseudo code as following:
1. get post body from http request;
2. call BlobToImage() to convert the posted data to a image for image handling such as resize/crop etc.;
3. call ImageToBlob() to format the handled image to blob and return to caller.
As for common image types other than PNG, this works fine.
When I want to convert a PNG file to the smallest filesize, i can not find the right way to set the effective params for ImageToBlob() , it tskes no effect!
But i find using cmd line works! like that: gm convert input.png -resize120x120 -depth 8 -colors 256 -quality 75 output.png.
With cmd line, parameter depth/colors/quality can works well.
depth can be set 1/2/4/8/16/24/32.
colors can be set 256.
As I try many ways to set those params in ImageToBlob(ImageInfo, Image), like depth in ImageInfo, depth/colors in Image, all are useless, filesize is not decreased much.
especially, depth set lower than 8 will be reset to 8 when call ImageToBlob.
I have read source code of GM 1.3.17, hope to take advantage of gm's implementation, but failed
Anyone can help? thanks a lot.
Your command line is requesting several image processing operations (e.g. resize). Between reading and writing the image, you would need to apply several image processing operations using the C API. Most of the code which does this for the command line is in MogrifyImage() in magick/command.c.
The PNG format itself does not support less "depth" than 8.
Bob
The PNG format supports depths less than 8 for grayscale and indexed images, but I'm not sure that the GM png encoder does.. By the way, -quality 70 will probably give you better compression than 75 for less-than-257-color images. If you are really concerned about PNG filesize, I recommend postprocessing them with pngcrush after you've written them with GM.
thanks to bfriesenand glennrp. I had read gm/coders/png.c, and found depth for png will be set to 8 if given less than 8. But how does gm make it with option -depth and -colors?
During ResizeImage(), it does not require any depth and colors paramters.
As for this:gm convert input.png -depth 8 -colors 256 -quality 75 output.png.
this cmd also takes effect and decrease filesize much.
So i am curious to find out how do GM to apply these options(depth and colors), as both of you say that PNG format does not support depth less than 8.
looking forwards to your reply.
riccy
Update:
I use SetImageDepth() to decrease the depth of image, this works!
Setting the depth from 8 to 4 reduceshalf of total filesize.
Another api SetImageColor() should also take the same effect, i will try later.
thanks all.
The functions you need to use are ResizeImage() http://www.graphicsmagick.org/api/resize.html#resizeimage and then QuantizeImage() http://www.graphicsmagick.org/api/quantize.html#quantizeimage, in that order. Once the image is resized and quantized, then set image->depth=8 and image->quality=75 before invoking ImageToBlob().
Glenn has already corrected me in that PNG can support fewer bits/sample for gray and colormapped images, however, I suspect that PNG still uses 8-bits per color sample for its color pallet.
Be careful about using SetImageDepth(). This function actually modifies the image pixels so that each quantum (color-component value) is cleanly representable in the specified number of bits. It does this by integer dividing and then multiplying. This will definitely make the output file smaller but also causes a loss of color quality since each color quantum can have no more than 16 values rather than 256. Using the image->depth=8 approach won't result in worse color quality.
hi bfriesen,
I read code of MogrifyImage() and try to use QuantizeImage() with the given QuantizeInfo structure, this also works.
No much difference between setting depth to 4 and setting colors to 256.
The following is my code refer to the code of MogrifyImage() in magick/command.c:
#define IMAGE_DEFAULT_DEPTH 24
#define IMAGE_DEFAULT_COLORS 65535
if (IMAGE_DEFAULT_DEPTH != param.depth) {
SetImageDepth(imgs.processed_image, param.depth);
}
if (IMAGE_DEFAULT_COLORS != param.colors) {
QuantizeInfo quantize_info;
GetQuantizeInfo(&quantize_info);
quantize_info.number_colors = param.colors;
quantize_info.tree_depth = 0;
quantize_info.dither = MagickTrue;
if (IsGrayColorspace(quantize_info.colorspace)) {
if (quantize_info.number_colors != 0)
(void) QuantizeImage(&quantize_info, imgs.processed_image);
else
(void) TransformColorspace(imgs.processed_image, quantize_info.colorspace);
} else {
if (quantize_info.number_colors != 0) {
if ((imgs.processed_image->storage_class == DirectClass) ||
(imgs.processed_image->colors > quantize_info.number_colors)) {
(void) QuantizeImage(&quantize_info, imgs.processed_image);
} else {
CompressImageColormap(imgs.processed_image);
}
}
}
}
This code is supposed to take effect when given depth or colors parameters.
thanks a lot.
riccy
I see that you have IMAGE_DEFAULT_DEPTH set to 24. Note that for an RGB image, image->depth would be 8 in that case.